Calling Circles UVA - 247 打电话 强连通分量

题目链接:
Calling Circles
刘汝佳紫书单源最短路例题之一。
题目大意:
有一群人打电话。如果有两个人互相打电话(直接或间接:a打给b,b打给c,c打给a,那么称 a 和 c 满是间接关系),求输出所有电话圈。
Limits:<=25

思路:
用 Floyd 算法跑一遍即可,再求出连通分量。具体题目按照Uva惯例,输入输出比较繁琐。

样例输入:
5 6
Ben Alexander
Alexander Dolly
Dolly Ben
Dolly Benedict
Benedict Dolly
Alexander Aaron
1 0
0 0
样例输出:
Calling circles for data set 1:
Ben, Alexander, Dolly, Benedict
Aaron

Calling circles for data set 2:

具体代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair <int,int> pii;
#define mem(s,t) memset(s,t,sizeof(s))
#define D(v) cout<<#v<<" "<<v<<endl
#define inf 0x3f3f3f3f
#define pb push_back

//#define LOCAL
const int mod=1e9+7;
const int MAXN =1000;
int N,M;
int a[MAXN][MAXN],vis[MAXN];
map<string,int> m;
map<int,string> ans;
int main() {
#ifdef LOCAL
    //freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
#endif
    int kase=0;
    while(cin>>N>>M && N+M){
        if(kase) puts("");
        cout<<"Calling circles for data set "<<++kase<<":\n";
        mem(a,0);
        mem(vis,0);
        m.clear();
        ans.clear();
        int cnt=1;
        for(int i=0;i<M;i++){
            string s1,s2;
            cin>>s1>>s2;
            if(!m[s1]) m[s1]=cnt++,ans[cnt-1]=s1;
            if(!m[s2]) m[s2]=cnt++,ans[cnt-1]=s2;
            a[m[s1]][m[s2]]=1;
        }
        //Floyd
        for(int k=1;k<=N;k++){
            for(int i=1;i<=N;i++){
                for(int j=1;j<=N;j++){
                    a[i][j]=a[i][j]||(a[i][k] && a[k][j]);
                }
            }
        }
        //Outputs
        for(int i=1;i<=N;i++){
            if(vis[i]) continue;
            cout<<ans[i];
            for(int j=i+1;j<=N;j++){
                if(vis[j]) continue;
                if(a[i][j] && a[j][i]){
                    cout<<", "<<ans[j];
                    vis[j]=1;
                }
            }
            cout<<endl;
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值