UVA247[Calling Circles] Floyed for Delivery Closure | tarjan for SCC

Title Link

Topic: If two people call each other (directly or indirectly), they say they are in the same telephone circle. For example, if a calls b, B calls c, C calls d and d calls a, then the four people are in the same circle; if e calls F and f does not call e, then E and F can not b e launched in the same circle. Enter m calls from n (n<=25) individuals and find out all the rings. Names contain only letters, not more than 25 characters, and do not repeat.

solution_1:tarjan Finds Directed Graph SCC

#include <map>
#include <stack> 
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
using namespace std;
const int N = 50;

vector<int> G[N];

stack<int> S;
int dfn[N], low[N];
bool bl[N];
int id;
map<string,int> mp1;
map<int,string> mp2;
int tot=0;
int Hash(string str){
    if( mp1.count(str) ) return mp1[str];
    mp1[str]=++tot;
    mp2[tot]=str;
    return tot;
} 
void dfs(int u){
    dfn[u]=low[u]=++id;
    S.push(u);
    bl[u]=true;
    for ( int i=0; i<G[u].size(); i++ ){
        int v=G[u][i];
        if( !dfn[v] ) {
            dfs(v);
            low[u]=min(low[u],low[v]);
        } else if( bl[v] ){
            low[u]=min(low[u],dfn[v]);
        }
    }
    if( low[u]==dfn[u] ){
        int ok=0;
        while( !S.empty()){
            int x=S.top(); S.pop();
            bl[x]=false;
            if( !ok ) cout<<mp2[x], ok=1;
            else cout<<", "<<mp2[x];
            if( x==u ) {
                break;
            }
        }
        cout<<"\n";
    }
}

void find_scc(int n){
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(bl,0,sizeof(bl));
    id=0;
    for ( int i=1; i<=n; i++ )
        if( !dfn[i] ) dfs(i); 
}

int n, m;
int main(){
    int k=0;
    while( ~scanf("%d%d", &n, &m ) && (n||m) ){
        if( k ) cout<<"\n";
        printf("Calling circles for data set %d:\n", ++k);  
        for ( int i=0; i<N; i++ ) G[i].clear();
        tot=0;
        mp1.clear(); mp2.clear();
        for ( int i=1; i<=m; i++ ){
            string s1,s2;
            cin>>s1>>s2;
            int x=Hash(s1), y=Hash(s2);
            G[x].push_back(y);  
        }
        find_scc(n);
    }
}

solution_2: Floyed for transitive closure

#include <map>
#include <stack> 
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
using namespace std;
const int N = 30;
int a[N][N];
bool vis[N];
map<string,int> mp1;
map<int,string> mp2;
int tot=0;
int Hash(string str){
    if( mp1.count(str) ) return mp1[str];
    mp1[str]=++tot;
    mp2[tot]=str;
    return tot;
} 
int n, m;
int main(){
    int k=0;
    while( ~scanf("%d%d", &n, &m ) && (n||m) ){
        if( k ) cout<<"\n";
        printf("Calling circles for data set %d:\n", ++k);  
        memset(a,0,sizeof(a));
        memset(vis,0,sizeof(vis));
        tot=0;
        mp1.clear(); mp2.clear();
        for ( int i=1; i<=m; i++ ){
            string s1,s2;
            cin>>s1>>s2;
            int x=Hash(s1), y=Hash(s2);
            a[x][y]=1;
        }
        for ( int k=1; k<=n; k++ )
            for ( int i=1; i<=n; i++ )
                for ( int j=1; j<=n; j++ )
                    a[i][j]=a[i][j] || (a[i][k]&&a[k][j]);
        for ( int i=1; i<=n; i++ ){
            if( vis[i] ) continue;
            vis[i]=1;
            cout<<mp2[i];
            for ( int j=1; j<=n; j++ ) 
                if( !vis[j] && a[i][j] && a[j][i] ) {
                    vis[j]=1;
                    cout<<", "<<mp2[j];
                }
            cout<<"\n";
        }
    }
}

Posted by NFWriter on Fri, 08 Feb 2019 12:54:17 -0800