UVA 247 Calling Circles

题目大意 如果两个人互相打电话(直接或间接),则说明他们在同一个电话圈里。但如果a打给b,b不打给a 就不算。(刘汝佳书上的描述简化)

因为题目数据范围很小 所以可以给所有打过电话的人直接建一条边,然后跑floyd,如果d[i][j]和d[j][i]都不是inf  i和j就是一个圈子里的

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cctype>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<algorithm>
#include<set>
#define scnaf scanf
#define cahr char
#define bug puts("bugbugbug");
using namespace std;
typedef long long ll;
const int inf=1000000000;
string print[100];
int d[100][100];
int f[100];
int n;
void init()
{
    for(int i=0; i<=30; i++)
        for(int j=0; j<=30; j++)
        {
            if(i==j)d[i][j]=0;
            else d[i][j]=inf;
        }
}
void Floyd()
{
    for(int k=1; k<=n; k++)
        for(int i=1; i<=n; i++)
            for(int j=1; j<=n; j++)
                if(d[i][k]<inf&&d[k][j]<inf)
                    d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
}
int Case=0;
void Print()
{
    int vis[30] = {0};
    if(Case) puts("");
    printf("Calling circles for data set %d:\n",++Case);
    for(int i = 1; i <= n; ++i) if(!vis[i])
        {
            cout<<print[i];
            vis[i] = 1;
            for(int j = 1; j <= n; ++j) if(!vis[j] && d[i][j]!=inf && d[j][i]!=inf)
                {
                    printf(", ");
                    cout<<print[j];//%s",name[j]);
                    vis[j] = 1;

                }
            puts("");
        }
}
map<string,int>mp;
int main()
{
    int m;
    while(~scnaf("%d%d",&n,&m)&&n+m)
    {

        mp.clear();
        init();
        string a,b;
        int cnt=1;
        for(int i=0; i<m; i++)
        {
            int aa,bb;
            cin>>a>>b;
            if(mp[a]==0)
            {
                mp[a]=cnt;
                print[cnt++]=a;
            }
            aa=mp[a];
            if(mp[b]==0)
            {
                mp[b]=cnt;
                print[cnt++]=b;
            }
            bb=mp[b];
            d[aa][bb]=1;
        }
        Floyd();
        Print();
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值