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-班长竞选的主要内容,如果未能解决你的问题,请参考以下文章

支持度的介绍

极客营JAVA十七营开营啦!未来看你的!

初到实训

第十天-用实力说话

去职班长三个月之后感想

Vijos 1921 严厉的班长 状态压缩动态规划