• [题解] 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(" ");
    printf("Calling circles for data set %d: ", ++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(" ");
    }
    }
    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("
    ");
    		printf("Calling circles for data set %d:
    ", ++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;
    }
    
  • 相关阅读:
    破周三,前不着村后不着店的,只好学pandas了,你该这么学,No.9
    周一不睡觉,也要把pandas groupy 肝完,你该这么学,No.8
    大周末的不休息,继续学习pandas吧,pandas你该这么学,No.7
    链接
    音乐
    术语
    新闻
    我的文章分类
    我的代码规则
    Jenkins 访问特别慢,且不消耗服务器资源
  • 原文地址:https://www.cnblogs.com/Anding-16/p/7380545.html
Copyright © 2020-2023  润新知