Uva247.Calling Circles(Floyd求连通性)

Uva247.Calling Circles (Floyd传递闭包)

Description

现有 n 个人(n25)个人打电话,若 a 打给b b 打给c c 打给a,则称 a,b,c 组成了一个电话圈。现在给出 n m条电话信息,求出所有的电话圈,并以任意顺序输出每个电话圈中的每个人。

Solution

Floyd传递闭包

通关传递闭包运算,求出每个人之间的连通性。当且仅当 ab ba 说明 a,b 在一个电话圈中。

Tarjan强连通分量

题面描述就是裸地Tarjan求强连通分量的题目,直接套板子就好。

Code

这里给出的是Floyd传递闭包的解法。

#include<bits/stdc++.h>
#define ll long long
#define nmax 50
using namespace std;
int mp[nmax][nmax];
bool isout[nmax];
string hashback[nmax];
map<string,int> mmp;
struct mes{
    string a,b;
}mes[nmax * nmax];
int n,m,cnt = 1;
void floyd(){
    for(int k = 1;k<=n;++k){
        for(int i = 1;i<=n;++i){
            for(int j = 1;j<=n;++j){
                if(mp[i][k])
                    mp[i][j] = mp[i][j] || (mp[i][k] && mp[k][j]);
            }
        }
    }
}
int main(){
//    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
    int kase = 1;
    while(cin>>n>>m){
        if(n == 0 && m ==0) break;
        if(kase>=2) cout<<endl;
        cnt = 1;mmp.clear();
        memset(mp,0,sizeof mp);
        for(int i = 0;i<m;++i){
            cin>>mes[i].a>>mes[i].b;
            if(mmp.count(mes[i].a) == 0) {mmp[mes[i].a] = cnt,hashback[cnt] = mes[i].a;cnt++;}
            if(mmp.count(mes[i].b) == 0) {mmp[mes[i].b] = cnt,hashback[cnt] = mes[i].b;cnt++;}
        }
        for(int i = 0;i<m;++i){
            string a = mes[i].a,b = mes[i].b;
            mp[mmp[a]][mmp[b]] = 1;
        }
        floyd();
        memset(isout,0,sizeof isout);
        cout<<"Calling circles for data set "<<kase++<<":"<<endl;
        for(int i = 1;i<=n;++i){
            if(isout[i]) continue;
            cout<<hashback[i];isout[i] = true;
            for(int j = 1;j<=n;++j){
                if(i!=j&&mp[i][j] && mp[j][i]){
                    cout<<", "<<hashback[j];
                    isout[j] = true;
                }
            }
            cout<<endl;
        }
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值