week8-C-班长竞选
Posted liuzhuan-xingyun
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了week8-C-班长竞选相关的知识,希望对你有一定的参考价值。
题意:
大学班级选班长,N 个同学均可以发表意见 若意见为 A B 则表示 A 认为 B 合适,意见具有传递性,即 A 认为 B 合适,B 认为 C 合适,则 A 也认为 C 合适 勤劳的 TT 收集了M条意见,想要知道最高票数,并给出一份候选人名单,即所有得票最多的同学,你能帮帮他吗?
Input
本题有多组数据。
第一行 T 表示数据组数。
每组数据开始有两个整数 N 和 M (2 <= n <= 5000, 0 <m <= 30000),
接下来有 M 行包含两个整数 A 和 B(A != B) 表示 A 认为 B 合适。
Output
对于每组数据,第一行输出 “Case x: ”,x 表示数据的编号,从1开始,紧跟着是最高的票数。
接下来一行输出得票最多的同学的编号,用空格隔开,不忽略行末空格!
Sample Input
2 4 3 3 2 2 0 2 1 3 3 1 0 2 1 0 2
Sample Output
Case 1: 2 0 1 Case 2: 2 0 1 2
My Solution:
SCC(Strong Connected Component)(极大强连通子图)
Kosaraju 算法: 学习链接
1.深度优先遍历G,算出每个结点u的结束时间f[u],起点如何选择无所谓。
2.深度优先遍历G的转置图G T ,选择遍历的起点时,按照结点的结束时间从大到小进行。遍历的过程中,一边遍历,一边给结点做分类标记,每找到一个新的起点,分类标记值就加1。
3. 第2步中产生的标记值相同的结点构成深度优先森林中的一棵树,也即一个强连通分量
缩点:
将属于同一个强连通分量的点合并,将同一个SCC的点合并成一个点,遍历反图中的每个点的边,如果边的两端不在同一SCC中则加入该边,最终形成新的缩点后的图。
Code:
1 #include<iostream> 2 #include<vector> 3 #include<queue> 4 #include<cstdio> 5 #include<cstring> 6 #include<functional> 7 using namespace std; 8 const int maxn = 30010; 9 int num,m,n,cnt,scnt,st,ta; 10 int ord[maxn],rord[maxn]; 11 int scc[maxn],dsc[maxn],indeg[maxn],ans[maxn]; 12 bool vis1[maxn],vis2[maxn],vis[maxn]; 13 vector<int> G1[maxn],G2[maxn],G3[maxn]; 14 void init() { 15 cnt = st = 0; 16 memset(vis,0,sizeof(vis)); 17 memset(vis1,0,sizeof(vis1)); 18 memset(vis2,0,sizeof(vis2)); 19 memset(indeg,0,sizeof(indeg)); 20 memset(scc,0,sizeof(scc)); 21 memset(dsc,0,sizeof(dsc)); 22 memset(ord,0,sizeof(ord)); 23 memset(rord,0,sizeof(rord)); 24 memset(ans,0,sizeof(ans)); 25 for(int i=0; i<=n; i++) { 26 G1[i].clear(); 27 G2[i].clear(); 28 G3[i].clear(); 29 } 30 } 31 void dfs1(int s) { 32 vis1[s] = true; 33 for(vector<int>::iterator i= G1[s].begin(); i!=G1[s].end(); i++) { 34 int d = *i; 35 if(!vis1[d]) { 36 dfs1(d); 37 } 38 } 39 cnt++; 40 ord[s] = cnt; 41 rord[cnt] = s; 42 } 43 void dfs2(int s) { 44 vis2[s] = true; 45 dsc[s] = st; 46 for(vector<int>::iterator i= G2[s].begin(); i!=G2[s].end(); i++) { 47 int d = *i; 48 if(!vis2[d]) { 49 scnt++; 50 dfs2(d); 51 } 52 } 53 } 54 void dfs3(int s) { 55 vis[s] = true; 56 ta += scc[s]; 57 for(vector<int>::iterator i= G3[s].begin(); i!=G3[s].end(); i++) { 58 int d = *i; 59 if(!vis[d]) { 60 dfs3(d); 61 } 62 } 63 } 64 int main() { 65 cin>>num; 66 int cn = 0; 67 while(num--) { 68 cn ++; 69 cin>>n>>m; 70 int a,b; 71 init(); 72 for(int i=0; i<m; i++) { 73 scanf("%d%d",&a,&b); 74 G1[a+1].push_back(b+1); 75 G2[b+1].push_back(a+1); 76 } 77 for(int i=1; i<=n; i++) { 78 if(!vis1[i]) dfs1(i); 79 } 80 for(int i=n; i>=1; i--) { 81 if(!vis2[rord[i]]) { 82 scnt = 1; 83 st++; 84 dfs2(rord[i]); 85 scc[st] = scnt; 86 } 87 } 88 for(int s=1; s<=n; s++) { 89 for(vector<int>::iterator i= G2[s].begin(); i!=G2[s].end(); i++) { 90 int d = *i; 91 if(dsc[s]!=dsc[d]) { 92 int u = dsc[s],v = dsc[d]; 93 indeg[v]++; 94 G3[u].push_back(v); 95 } 96 } 97 } 98 for(int i=1; i<=st; i++) { 99 if(indeg[i]==0) { 100 ta = 0; 101 memset(vis,0,sizeof(vis)); 102 dfs3(i); 103 ans[i] = ta - 1; 104 } 105 } 106 int MaxAns = 0; 107 queue<int> ansq; 108 for(int i=1; i<=st; i++) { 109 MaxAns = max(MaxAns,ans[i]); 110 } 111 // cout<<endl; 112 for(int i=1; i<=st; i++) { 113 if(MaxAns==ans[i]) { 114 ansq.push(i); 115 } 116 } 117 priority_queue<int,vector<int>,greater<int> > output; 118 while(ansq.size()) { 119 int tmp = ansq.front(); 120 ansq.pop(); 121 for(int i=1; i<=n; i++) { 122 if(dsc[i]==tmp) output.push(i-1); 123 } 124 } 125 printf("Case %d: %d ",cn,MaxAns); 126 while(output.size()>1){ 127 printf("%d ",output.top()); 128 output.pop(); 129 } 130 printf("%d ",output.top()); 131 output.pop(); 132 } 133 return 0; 134 }
以上是关于week8-C-班长竞选的主要内容,如果未能解决你的问题,请参考以下文章