Uva247 Floyd传递闭包+map处理

链接:https://vjudge.net/problem/UVA-247 


题意:a打给b,b打给c,c打给d,d打给a,那么这四个人就在一个圈里,具有传递性,离散数学传递闭包的经典题目,a可以通过bc到达d,因为d可以到达a,所以a和d在一个圈,b可以通过cd到达a,a也可以到达b,所以ab在一个圈。如果e打给f,f不能直接或者间接打给e,那么这两个人就不在一个圈,找出所有的圈。

n最大才25,不怕超时了,floyd三重循环暴力解决

利用floyd的中间传递松弛性恰好解决。

#include <bits/stdc++.h>

using namespace std;
map<string,int>name;
vector<string>Name;
int n,m;
int vis[30];
int d[30][30];
int id;//没什么用,就是给name逐增赋值
void floyd() {
    for(int k = 0; k < n; k++)
        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++)
                d[i][j] = d[i][j]||(d[i][k]&&d[k][j]);
    }

void dfs(int u) {
    vis[u] = 1;
    for(int i = 0; i < n; i++) {
            if(!vis[i]&&d[u][i]&&d[i][u]) {
                cout<<", "<<Name[i];
                dfs(i);
        }
    }
}


int main() {
//    freopen("in.txt","r",stdin);
    int casen = 1;

    while(cin>>n>>m) {
        if(n==0&&m==0)
            break;
            Name.clear();
            name.clear();
            memset(d,0,sizeof(d));
            memset(vis,0,sizeof(vis));
            id =0;
        while(m--) {
            string a,b;
            cin>>a>>b;
            //count()函数返回map中键值等于key的元素的个数,就只能为
            //1或者0,专门判断一个键值值是否存在map里面,前提是这个键值赋了key值。
            if(!name.count(a)) {
                name[a] = id;
                id++;
                Name.push_back(a);
            }

            if(!name.count(b)) {
            name[b] = id;
            id++;
            Name.push_back(b);
            }

            d[name[a]][name[b]] = 1;
        }
            floyd();
            if(casen>1)
                cout<<endl;
            printf("Calling circles for data set %d:
",casen);
            casen++;
            for(int i = 0; i < n; i++) {
                if(!vis[i]) {
                    cout<<Name[i];
                    dfs(i);
                    cout<<endl;;
                }
            }
        }
    }




原文地址:https://www.cnblogs.com/zhangmingzhao/p/7256637.html