UVA 247"Calling Circles"(floyd求传递闭包+SCC)

传送门

 

题意:

  如果两个人相互打电话(直接或间接),则说他们在同一个电话圈里。

  (a,b) 表示 a 打给 b;

  例如,(a,b),(b,c),(c,d),(d,a),则这四个人在同一个电话圈里;

  输入 n(n≤25) 个人的 m 次电话,找出所有的电话圈,输出每个电话圈里的人名(无序)。

题解:

  首先用floyd求出传递闭包,构造新图;

  然后在新图上跑一遍SCC求解;

AC代码:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define memF(a,b,n) for(int i=0;i <= n;a[i]=b,++i);
  4 const int maxn=30;
  5 
  6 int n,m;
  7 int num;
  8 int head[maxn];
  9 struct Edge
 10 {
 11     int to;
 12     int next;
 13 }G[maxn*maxn*2];
 14 void addEdge(int u,int v)
 15 {
 16     G[num]={v,head[u]};
 17     head[u]=num++;
 18 }
 19 map<string ,int >f;
 20 map<int ,string >g;
 21 bitset<maxn>_bit[maxn];
 22 int col[maxn];
 23 struct SCC
 24 {
 25     vector<int >vs;
 26     bool vis[maxn];
 27     void DFS(int u)
 28     {
 29         vis[u]=true;
 30         for(int i=head[u];~i;i=G[i].next)
 31         {
 32             int v=G[i].to;
 33             if(vis[v] || (i&1))
 34                 continue;
 35             DFS(v);
 36         }
 37         vs.push_back(u);
 38     }
 39     void RDFS(int u,int k)
 40     {
 41         vis[u]=true;
 42         col[u]=k;
 43         for(int i=head[u];~i;i=G[i].next)
 44         {
 45             int v=G[i].to;
 46             if(vis[v] || !(i&1))
 47                 continue;
 48             RDFS(v,k);
 49         }
 50     }
 51     void scc()
 52     {
 53         vs.clear();
 54         memF(vis,false,n);
 55         for(int i=1;i <= n;++i)
 56             if(!vis[i])
 57                 DFS(i);
 58 
 59         memF(vis,false,n);
 60         int k=0;
 61         for(int i=vs.size()-1;i >= 0;--i)
 62             if(!vis[vs[i]])
 63                 RDFS(vs[i],++k);
 64     }
 65 }_scc;
 66 vector<int >vs[maxn];
 67 void Solve()
 68 {
 69     for(int i=1;i <= n;++i)///传递闭包
 70         for(int j=1;j <= n;++j)
 71             if(_bit[j][i])
 72                 _bit[j] |= _bit[i];
 73     for(int i=1;i <= n;++i)///构图
 74         for(int j=1;j <= n;++j)
 75             if(_bit[i][j])
 76             {
 77                 addEdge(i,j);
 78                 addEdge(j,i);
 79             }
 80     _scc.scc();
 81     for(int i=1;i <= n;++i)
 82         vs[i].clear();
 83     for(int i=1;i <= n;++i)
 84         vs[col[i]].push_back(i);
 85 
 86     for(int i=1;i <= n;++i)
 87     {
 88         bool flag=false;
 89         for(int j=0;j < vs[i].size();++j)
 90         {
 91             if(!flag)
 92             {
 93                 cout<<g[vs[i][j]];
 94                 flag=true;
 95             }
 96             else
 97                 cout<<", "<<g[vs[i][j]];
 98         }
 99         if(flag)
100             printf("\n");
101     }
102 }
103 void Init()
104 {
105     num=0;
106     memF(head,-1,n);
107     f.clear();
108     g.clear();
109     for(int i=0;i <= n;++i)
110         _bit[i].reset();
111 }
112 int main()
113 {
114 //    freopen("C:\\Users\\hyacinthLJP\\Desktop\\in&&out\\contest","r",stdin);
115     bool flag=false;
116     int kase=0;
117     while(~scanf("%d%d",&n,&m) && n+m)
118     {
119         Init();
120         int k=0;
121         for(int i=1;i <= m;++i)
122         {
123             string s1,s2;
124             cin>>s1>>s2;
125             if(!f.count(s1))
126             {
127                 f[s1]=++k;
128                 g[k]=s1;
129             }
130             if(!f.count(s2))
131             {
132                 f[s2]=++k;
133                 g[k]=s2;
134             }
135             _bit[f[s1]].set(f[s2]);
136         }
137         if(flag)
138             printf("\n");
139         flag=true;
140         printf("Calling circles for data set %d:\n",++kase);
141         Solve();
142     }
143     return 0;
144 }
View Code

 

posted @ 2019-05-30 08:14  HHHyacinth  阅读(301)  评论(0编辑  收藏  举报