UVa 247 - Calling Circles(Floyd求有向图的传递闭包)
Posted hkxy125
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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个字符,且不重复。
分析:
首先用floyd求出传递闭包,即G[i][j]表示i是否直接或者间接给j打过电话。
则当且仅当G[i][j]=G[j][i]=true时二者处于一个电话圈。
依此结论直接判断输出即可。
代码:
1 import java.io.*; 2 import java.util.*; 3 import static java.util.Arrays.*; 4 5 public class Main { 6 Scanner cin = new Scanner(new BufferedInputStream(System.in)); 7 final int UP = 25 + 5; 8 boolean vis[] = new boolean[UP], G[][] = new boolean[UP][UP]; 9 ArrayList<String> name = new ArrayList<String>(); 10 11 int id(String s) { 12 for(int i = 0; i < name.size(); i++) { 13 if(name.get(i).equals(s)) return i; 14 } 15 name.add(s); 16 return name.size() - 1; 17 } 18 19 void MAIN() { 20 for(int cases = 1; ; cases++) { 21 int n = cin.nextInt(); 22 int m = cin.nextInt(); 23 if(n == 0 && m == 0) break; 24 name.clear(); 25 for(int t = 0; t < n; t++) 26 for(int i = 0; i < n; i++) G[t][i] = false; 27 for(int i = 0; i < m; i++) 28 G[id(cin.next())][id(cin.next())] = true; 29 30 for(int i = 0; i < n; i++) G[i][i] = true; 31 for(int k = 0; k < n; k++) { 32 for(int i = 0; i < n; i++) { 33 for(int j = 0; j < n; j++) G[i][j] |= G[i][k] & G[k][j]; 34 } 35 } 36 37 if(cases > 1) System.out.println(); 38 System.out.printf("Calling circles for data set %d: ", cases); 39 fill(vis, false); 40 for(int t = 0; t < n; t++) { 41 if(vis[t]) continue; 42 System.out.printf("%s", name.get(t)); 43 for(int i = t+1; i < n; i++) { 44 if(G[t][i] && G[i][t]) { 45 System.out.printf(", %s", name.get(i)); 46 vis[i] = true; 47 } 48 } 49 System.out.println(); 50 } 51 } 52 } 53 54 public static void main(String args[]) { new Main().MAIN(); } 55 }
以上是关于UVa 247 - Calling Circles(Floyd求有向图的传递闭包)的主要内容,如果未能解决你的问题,请参考以下文章