zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    Mac 虚拟机VMware Fusion显示内部错误的解决方法
    Linux系统中的引导过程与服务控制
    linux系统中如何删除lvm分区
    Linux命令下: LVM逻辑卷配置过程详解(创建,增加,减少,删除,卸载)
    解决:rm: 无法删除"tomcat": 设备或资源忙
    LVM操作过程
    Linux命令下进行硬盘挂载、分区、删除分区,格式化,卸载方法
    finger 命令查询用户名、主目录、停滞时间、登录时间
    【MySQL】MySQL5.7传统复制切换为GTID复制
    深入理解MySQL系列之锁
  • 原文地址:https://www.cnblogs.com/liuzhuan-xingyun/p/12717975.html
Copyright © 2011-2022 走看看