【UVA】247 - Calling Circles(floyd判断包闭,dfs输出)

最近状态不佳,总是爱犯低级错误,比较水的题,没什么需要讲得,要说的可能是floyd判断包闭吧

void Floyd()
{
    for(int k=1; k<=n; k++)
        for(int i=1; i<=n; i++)
            if(map[i][k])
                for(int j=1; j<=n; j++)
                    if(map[k][j])
                        map[i][j] = 1;
}  

之前做了不少图论,图论周感觉能应付的过去。

14059727 247 Calling Circles Accepted C++ 0.058 2014-08-18 12:21:42
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<list>
#include<cmath>
#include<string>
#include<sstream>
#include<ctime>
using namespace std;
#define _PI acos(-1.0)
#define esp 1e-9
#define INF 1 << 30
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> pill;
/*===========================================
===============KinderRiven===================
===========================================*/
#define MAXD 25 + 1
int n,m;
map<string,int>name;
vector<string>Name;
int G[MAXD][MAXD],id;
int vis[MAXD];
void init(){
    name.clear();
    Name.clear();
    id = 0;
    memset(G,0,sizeof(G));
    memset(vis,0,sizeof(vis));
}
void dfs(int u){
    vis[u] = 1;
    for(int i = 0 ; i < n ; i++)
        if(G[u][i] == 1 && G[u][i] == G[i][u]){
         if(!vis[i]){
            cout << ", " << Name[i];
            dfs(i);
         }
    }
}
int main(){
    int Case = 1;
    while(cin >> n >> m){
        init();
        if(!n && !m) break;
        for(int i = 0 ; i < m ; i++){
            string s1,s2;
            cin >> s1 >> s2;
            if(!name.count(s1)){
                name[s1] = id++;
                Name.push_back(s1);
            }
            if(!name.count(s2)){
                name[s2] = id++;
                Name.push_back(s2);
            }
            int x = name[s1] , y = name[s2];  /*找出2个字符串对应的ID*/
            G[x][y] = 1;                      /*连接*/
        }
        for(int k = 0 ; k < n ; k++)
            for(int i = 0 ; i < n ; i++)
                if(G[i][k])
                for(int j = 0; j < n ; j++)
                    if(G[k][j]){
                       G[i][j] = 1;
                }
        if(Case > 1)
        cout << endl;
        cout << "Calling circles for data set " << Case++ <<":" << endl;
        for(int i = 0; i < n ; i++){
            if(!vis[i]){
                cout << Name[i];
                dfs(i);
                cout << endl;
            }
        }
    }
    return 0;
}
/*
5 5
A B
A B
A B
C D
E C
*/

【UVA】247 - Calling Circles(floyd判断包闭,dfs输出)

时间: 2024-10-29 19:05:32

【UVA】247 - Calling Circles(floyd判断包闭,dfs输出)的相关文章

uva 247 Calling Circles(Floyd 的简单应用)

最近在看图论的经典算法, 先看的是求单源最短路的dijkstra,优化后的算法用了优先队列,看起来有点复杂. 感觉 弗洛伊德(Floyd) 要比 迪克斯特拉(dijkstra) 更好理解一点,但是Floyd是三层循环,当然会慢很多.一旦数据开大就跪了吧. floyd可以用来求 两个 连通点间的最短路问题.同时可以得到边权的和,即最短路的长度. 另外一个比较简单的应用,还可以用来判断两点间的连通性.即判断两点是否连通.本题就是弗洛伊德的这种简单用法. #include<cstdio> #incl

UVa 247 - Calling Circles(Floyd求有向图的传递闭包)

链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=183 题意: 如果两个人相互打电话(直接或间接),则说他们在同一个电话圈里.例如,a打给b,b打给c,c打给d,d打给a,则这4个人在同一个圈里:如果e打给f但f不打给e,则不能推出e和f在同一个电话圈里.输入n(n≤25)个人的m次电话,找出所有电话圈.人名只包含字母,不超过25个

UVa 247 Calling Circles【传递闭包】

题意:给出n个人的m次电话,问最后构成多少个环,找出所有的环 自己想的是:用map来储存人名,每个人名映射成一个数字编号,再用并查集,求出有多少块连通块,输出 可是map不熟,写不出来,而且用并查集输出的时候感觉貌似很麻烦 然后再用的传递闭包,可是判断到d[i][j]==1和d[j][i]==1,该怎么输出路径呢 于是看了lrj的代码= = 用的是一个ID(string s)函数来给名字编号,和第五章的集合栈计算机那题的办法一样 然后用dfs输出路径= =(这个要好好--好好--好好学) 最后还

11.3.4 例题11-4 UVA 247 Calling Circles (有向图的传递闭包)

题目大意: 给你n个人,m条边,a->b,b->a,才能说这两个人是联通的.问现在有多少个联通圈.输出每个联通圈.n<=25 解题思路: 直接建图,用有向图的闭包传递特性来处理每个人之间的联通关系.然后dfs一次,遍历邻接矩阵中与某个点相连的几个点,边遍历, 边打印输出. 代码: # include<cstdio> # include<iostream> # include<map> # include<cstring> # include

247 - Calling Circles (Floyd 求传递闭包)

该题恰好用到刚刚讲到的Floyd求传递闭包 , 因为该题的数据量不是很大, 要是大了估计就要用其他方法了 .  但是这毕竟是一个很简单易写的算法 . 求出传递闭包之后就用并查集将在一个电话圈的人合并在一起,最后输出 . 细节参见代码: #include<bits/stdc++.h> using namespace std; int n,m,d[30][30],par[30],kase = 0; string s1,s2; map<string , int > p; map<i

UVa247 Calling Circles (Floyd,DFS)

链接:http://bak3.vjudge.net/problem/UVA-247 分析:先用Floyd求出有向图的传递闭包,然后用DFS求出各个联通分量即可. 1 #include <cstdio> 2 #include <cstring> 3 #include <vector> 4 #include <string> 5 using namespace std; 6 7 vector<string> names; 8 int ID(const

UVa 247 (传递闭包) Calling Circles

题意: 有n个人m通电话,如果有两个人相互打电话(直接或间接)则在同一个电话圈里.输出所有电话圈的人的名单. 分析: 根据打电话的关系,可以建一个有向图,然后用Warshall算法求传递闭包. 最后输出是辅助一个标记数组,用DFS输出的,这个办法挺巧妙的. 本来我原来的想法是,用并查集求所有的连通分量,然后再好多次循环找连通分量一致的名字输出,那样太麻烦了. ios::sync_with_stdio(false);这个最好不要随便用,可能会产生某些副作用. 字符指针是可以传给string对象作参

UVA 247 电话圈 (floyd传递闭包 + dfs输出连通分量)

题意:输出所有的环: 思路:数据比较小,用三层循环的floyd传递闭包(即两条路通为1,不通为0,如果在一个环中,环中的所有点能互相连通),输出路径用dfs,递归还没有出现过的点(vis),输出并递归该点与其他点能互达的点: 1 #include <cstdio> 2 #include <vector> 3 #include <string> 4 #include <cstring> 5 #include <iostream> 6 using n

UVa 247 电话圈(Floyd传递闭包)

https://vjudge.net/problem/UVA-247 题意: 如果两个人相互打电话,则说他们在同一个电话圈里.例如,a打给b,b打给c,c打给d,d打给a,则这4个人在同一个圈里:如果e打给f但f不打给e,则不能推出e和f在同一个电话圈里,输出所有电话圈. 思路: 通过Floyd求一个传递闭包.最后dfs输出每一个电话圈即可. 传递闭包的求法: 1 for (int k = 0; k < n;k++) 2 for (int i = 0; i < n;i++) 3 for (in