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<vector>
# include<set>
using namespace std;
# define MAX 55
map<string,int>MP;
vector<string>name;
int e[MAX][MAX];
int vis[MAX];
int n,m;
int change ( string s )
{
    for ( int i = 0;i < name.size();i++ )
    {
        if ( name[i]==s )
            return i;
    }
    name.push_back(s);
    return name.size()-1;
}
void dfs( int u )
{
    vis[u] = 1;
    for ( int v = 0;v < n;v++ )
    {
        if ( vis[v]==0&&e[u][v]&&e[v][u] )
        {
            cout<<","<<" "<<name[v];
            dfs(v);
        }
    }
    return;
}
int main(void)
{
    int icase = 1;
    while ( scanf("%d%d",&n,&m)!=EOF )
    {
        if ( n==0&&m==0 )
            break;
        memset(e,0,sizeof(e));
        name.clear();
        while ( m-- )
        {
            string s1,s2; cin>>s1>>s2;
            int t1 = change(s1);
            int t2 = change(s2);
            e[t1][t2] = 1;
        }
        for ( int i = 0;i < n;i++ )
            e[i][i] = 1;
        for ( int k = 0;k < n;k++ )
        {
            for ( int i = 0;i < n;i++ )
            {
                for ( int j = 0;j < n;j++ )
                {
                    e[i][j] = e[i][j]||(e[i][k]&&e[k][j]);
                }
            }
        }
         if ( icase )
            puts("");
        printf("Calling circles for data set %d:\n",icase++);
        memset(vis,0,sizeof(vis));
        for ( int i = 0;i < n;i++ )
        {
            if (vis[i]==0)
            {
                cout<<name[i];
                dfs(i);
                puts("");
            }
        }
    }
    return 0;
}

  

时间: 2024-08-06 20:03:33

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

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输出路径= =(这个要好好--好好--好好学) 最后还

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

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

【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.0

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

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

mod_tile编译出错 -std=c++11 or -std=gnu++11

make[1]: 正在进入目录 /home/wml/src/mod_tile-master' depbase=echo src/gen_tile.o | sed 's|[^/]*$|.deps/&|;s|.o$||'`;\ g++ -DHAVE_CONFIG_H -I. -I./includes -I/usr/include/freetype2 -pthread -I/usr/local/include -I/usr/local/include/mapnik/agg -I/usr/include

淘宝双十一11促销神奇,双11十一充值送红包攻略,双11十一买手机有优惠吗淘宝活动详情

[双十一活动家装汽车会场] 简单,有弹性,喇叭口蛮大的.发过来淘宝双十一11促销神奇,双11十一充值送红包攻略,双11十一买手机有优惠吗的大了,本来想换的,还是怕麻烦,算了,送别人吧 .以后早点联系啊. 不错,慢慢都爱上茵曼了,价格便宜货也不错, 漂亮!!!!!!!!! 正穿着,颜色很艳 [双十一活动主会场] 买大了,75元转,有兴趣的mm联系我,旺旺:秋81705774 [>>>点此查看更多会场] 软软的,手感很好,很喜欢,物流也快,满意, 很好看,就是大了些 很好的宝贝! 颜色看上去