[题解] uva 247 Calling Circles (floyd判联通/tarjan强连通分量)

- 传送门 -

 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=183

# 247 - Calling Circles Time limit: 3.000 seconds | [Root](https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=0) | [![Submit](https://uva.onlinejudge.org/components/com_onlinejudge/images/button_submit.png "Submit")](https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=submit_problem&problemid=183&category=) [![Problem Stats](https://uva.onlinejudge.org/components/com_onlinejudge/images/button_stats.png "Problem Stats")](https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=problem_stats&problemid=183&category=) [![uDebug](https://uva.onlinejudge.org/components/com_onlinejudge/images/button_debug.png)](https://www.udebug.com/UVa/247) [![Download as PDF](https://uva.onlinejudge.org/components/com_onlinejudge/images/button_pdf.png "Download as PDF")](https://uva.onlinejudge.org/external/2/247.pdf) | ###(题面见pdf)
  ### - 题意 -  给出n, m, 表示 n 个人打了 m 个单向电话, 若两个人互通了电话(直接或间接), 就称他们在一个电话圈里, 问每个电话圈有那些人.   ### - 思路 -  floyd: G[i][j]表示 i 向 j 连线, 过一遍 floyd 可以使间接通话变为直接(G[i][j] = G[i][j] || (G[i][k] && G[k][j])), 然后 dfs 查找和一个人互相直接通话的人(G[x][y]&&G[y][x]), 则他们在一个电话圈里.    tarjan: 其实这题我第一反应是强连通分量...强连通分量即是"电话圈".    细节见代码.   ### - 代码 - floyd: ```c++ #include #include #include #include #include #include using namespace std;

const int N = 30;

int G[N][N], VIS[N];
int n, m, id, cas;

map<string, int>name;
map<int, string>NAME;

void init() {
id = 0;
memset(VIS, 0, sizeof (VIS));
memset(G, 0, sizeof (G));
name.clear();
NAME.clear();
}

void floyed() {
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
for (int k = 1; k <= n; ++k) {
if (G[i][k] && G[k][j]) G[i][j] = 1;
if (G[j][k] && G[k][i]) G[j][i] = 1;
}
}

void dfs(int x) {
VIS[x] = 1;
for (int i = 1; i <= n; ++i)
if (G[x][i] && G[i][x] && !VIS[i]) {
cout<<", "<<NAME[i];
dfs(i);
}
}

int main() {
while (scanf("%d%d", &n, &m) != EOF && n && m) {
if (cas) printf("\n");
printf("Calling circles for data set %d:\n", ++cas);
init();
string S1, S2;
for (int i = 1; i <= m; ++i) {
cin>>S1>>S2;
if (name.find(S1) == name.end()) {
name[S1] = ++id;
NAME[id] = S1;
}
if (name.find(S2) == name.end()) {
name[S2] = ++id;
NAME[id] = S2;
}
G[name[S1]][name[S2]] = 1;
}
floyed();
for (int i = 1; i <= n; ++i) {
if (VIS[i]) continue;
cout<<NAME[i];
dfs(i);
printf("\n");
}
}
return 0;
}


tarjan:
```c++
#include<cstdio>
#include<map>
#include<vector>
#include<string>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;

const int N = 30;

int G[N][N], VIS[N];
int DFN[N], LOW[N], STK[N], INSTK[N];
int n, m, id, sz, tot, cas;

map<string, int>name;
map<int, string>NAME;
vector<int>S[N];

void init() {
	id = sz = tot = 0;
	memset(DFN, 0, sizeof (DFN));
	memset(INSTK, 0, sizeof (INSTK));
	memset(G, 0, sizeof (G));
	name.clear();
	NAME.clear();
	for (int i = 1; i <= n; ++i)
		S[i].clear();
}

void tarjan(int x) {
	DFN[x] = LOW[x] = ++tot;
	STK[++sz] = x; INSTK[x] = 1;
	for (int i = 1; i <= n; ++i) {
		if (G[x][i]) {
			if (!DFN[i]) { tarjan(i); LOW[x] = min(LOW[i], LOW[x]); }
			else if (INSTK[i]) LOW[x] = min(DFN[i], LOW[x]);
		}
	}
	if (DFN[x] == LOW[x]) {
		while (STK[sz] != x) {
			INSTK[STK[sz]] = 0;
			cout<<NAME[STK[sz--]];
			printf(", ");
		}
		INSTK[STK[sz]] = 0;
		cout<<NAME[STK[sz--]]<<endl;
	}
}

void dfs(int x) {
	VIS[x] = 1;
	for (int i = 1; i <= n; ++i)
		if (G[x][i] && G[i][x] && !VIS[i]) {
			cout<<", "<<NAME[i];
			dfs(i);
		}
}



int main() {
	while (scanf("%d%d", &n, &m) != EOF && n && m) {
		if (cas) printf("\n");
		printf("Calling circles for data set %d:\n", ++cas);
		init();
		string S1, S2;
		for (int i = 1; i <= m; ++i) {
			cin>>S1>>S2;
			if (name.find(S1) == name.end()) {
				name[S1] = ++id;
				NAME[id] = S1;
			}
			if (name.find(S2) == name.end()) {
				name[S2] = ++id;
				NAME[id] = S2;
			}
			G[name[S1]][name[S2]] = 1;
		}
		for (int i = 1; i <= n; ++i)
			if (!DFN[i]) tarjan(i);
	}
	return 0;
}
posted @ 2017-08-17 11:08  lstttt  阅读(140)  评论(0编辑  收藏  举报