连通图练习总结

强颜欢笑 提交于 2020-03-20 08:04:18

连通图是图论基于联通的一个概念,在ACM中针对图论的考察一部分是也是基于连通图。针对这类问题的解题基本思路就是先求出对应的连通分量(有向图的强连通,无向图的双连通)对图进行简化,然后再结合其他算法计算。

1. POJ 3180 The Cow Prom

这个题如果能理解题目的话,怎么做就很明显了,能形成一个可以转圈的小群,就相当于一个强连通分量,需要注意的就是这个小群不可以只有一头牛。

#include <set>
#include <map>
#include <list>
#include <stack>
#include <queue>
#include <ctime>
#include <cmath>
#include <cstdio>
#include <vector>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

#pragma comment(linker, "/STACK:1024000000,1024000000")

#define     IT              iterator
#define     PB(x)           push_back(x)
#define     CLR(a,b)        memset(a,b,sizeof(a))

using namespace std;

typedef     long long               ll;
typedef     unsigned long long      ull;
typedef     vector<int>             vint;
typedef     vector<ll>              vll;
typedef     vector<ull>             vull;
typedef     set<int>                sint;
typedef     set<ull>                sull;

const int maxn = 10000 + 5;
vint G[maxn];
int pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,scc_cnt;
stack<int> S;
int a[maxn];

void init(int n) {
    for (int i = 0; i <= n; i++) G[i].clear();
}

void dfs(int u) {
    pre[u] = lowlink[u] = ++dfs_clock;
    S.push(u);
    for (int i = 0; i < G[u].size(); i++) {
        int v = G[u][i];
        if (!pre[v]) {
            dfs(v);
            lowlink[u] = min(lowlink[u],lowlink[v]);
        }
        else if (!sccno[v]) {
            lowlink[u] = min(lowlink[u],pre[v]);
        }
    }
    if (lowlink[u] == pre[u]) {
        scc_cnt++;
        while (1) {
            int x = S.top();
            S.pop();
            sccno[x] = scc_cnt;
            if (x == u) break;
        }
    }
}

void find_scc(int n) {
    dfs_clock = scc_cnt = 0;
    CLR(sccno,0);
    CLR(pre,0);
    for (int i = 1; i <= n; i++) {
        if (!pre[i]) dfs(i);
    }
}

int cnt[maxn];

int main() {
    int n,m;
    //freopen("data.in","r",stdin);
    while (cin>>n>>m) {
        init(n);
        for (int i = 0; i < m; i++) {
            int a,b;
            scanf("%d%d",&a,&b);
            G[a].PB(b);
        }
        //for (int i = 0; i <= scc_cnt; i++) new_g[i].clear();
        find_scc(n);
        for (int i = 1; i <= n; i++) {
            cnt[sccno[i]]++;
        }
        int ans = 0;
        /*cout<<scc_cnt<<endl;
        for (int i = 1; i <= scc_cnt; i++) {
            for (int j = 0; j < new_g[i].size(); j++) {
                cout<<i<<" "<<new_g[i][j].from<<" "<<new_g[i][j].cost<<endl;
            }
        }*/
        for (int i = 1; i <= scc_cnt; i++) {
            if (cnt[i] > 1) ans++;
        }
        cout<<ans<<endl;
    }
}

 2. POJ 1236 Network of Schools

最开始对于图的处理同样也是需要用强连通缩点重新构图,然后针对两个任务,第一个很好理解就是入度为0的强连通个数,第二个问题需要小小想一下,欲将整个图变成一个强连通,那么就相当于把现在的图中入度为0和出度为0的点都消灭掉(加边),那么想到这里答案就出来了,就是max{入度为0的点个数,出度为0的点个数}。

#include <set>
#include <map>
#include <list>
#include <stack>
#include <queue>
#include <ctime>
#include <cmath>
#include <cstdio>
#include <vector>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

#pragma comment(linker, "/STACK:1024000000,1024000000")

#define     IT              iterator
#define     PB(x)           push_back(x)
#define     CLR(a,b)        memset(a,b,sizeof(a))

using namespace std;

typedef     long long               ll;
typedef     unsigned long long      ull;
typedef     vector<int>             vint;
typedef     vector<ll>              vll;
typedef     vector<ull>             vull;
typedef     set<int>                sint;
typedef     set<ull>                sull;

const int maxn = 10000 + 5;
vint G[maxn];
int pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,scc_cnt;
stack<int> S;
int a[maxn];

void init(int n) {
    for (int i = 0; i <= n; i++) G[i].clear();
}

void dfs(int u) {
    pre[u] = lowlink[u] = ++dfs_clock;
    S.push(u);
    for (int i = 0; i < G[u].size(); i++) {
        int v = G[u][i];
        if (!pre[v]) {
            dfs(v);
            lowlink[u] = min(lowlink[u],lowlink[v]);
        }
        else if (!sccno[v]) {
            lowlink[u] = min(lowlink[u],pre[v]);
        }
    }
    if (lowlink[u] == pre[u]) {
        scc_cnt++;
        while (1) {
            int x = S.top();
            S.pop();
            sccno[x] = scc_cnt;
            if (x == u) break;
        }
    }
}

void find_scc(int n) {
    dfs_clock = scc_cnt = 0;
    CLR(sccno,0);
    CLR(pre,0);
    for (int i = 1; i <= n; i++) {
        if (!pre[i]) dfs(i);
    }
}

int in[maxn];
int out[maxn];

int main() {
    int n,m;
    //freopen("data.in","r",stdin);
    while (cin>>n) {
        init(n);
        for (int i = 1; i <= n; i++) {
            int m;
            while (scanf("%d",&m),m) {
                G[i].PB(m);
            }
        }
        //for (int i = 0; i <= scc_cnt; i++) new_g[i].clear();
        find_scc(n);
        CLR(in,0);
        CLR(out,0);
        int tmpa = 0,tmpb = 0;
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j < G[i].size(); j++) {
                int v = G[i][j];
                if (sccno[i] != sccno[v]) {
                    out[sccno[i]]++;
                    in[sccno[v]]++;
                }
            }
        }
        for (int i = 1; i <= scc_cnt; i++) {
            if (!out[i]) tmpb++;
            if (!in[i]) tmpa++;
        }
        cout<<tmpa<<endl<<(scc_cnt == 1 ? 0 : max(tmpb,tmpa))<<endl;
    }
}

 3. POJ 2186 Popular Cows

题目给出一些仰慕关系,需要求的是被所有牛仰慕的牛的个数。由于图相对比较大,所以先强连通缩点,重新构图之后,这样之后就相对简单了,保证图连通的情况下,我们需要保证出度为0的分量只有一个,如果有多个,那么这几个分量之间必然没有倾慕关系。

#include <set>
#include <map>
#include <list>
#include <stack>
#include <queue>
#include <ctime>
#include <cmath>
#include <cstdio>
#include <vector>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

#pragma comment(linker, "/STACK:1024000000,1024000000")

#define     IT              iterator
#define     PB(x)           push_back(x)
#define     CLR(a,b)        memset(a,b,sizeof(a))

using namespace std;

typedef     long long               ll;
typedef     unsigned long long      ull;
typedef     vector<int>             vint;
typedef     vector<ll>              vll;
typedef     vector<ull>             vull;
typedef     set<int>                sint;
typedef     set<ull>                sull;

const int maxn = 10000 + 5;
vint G[maxn];
int pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,scc_cnt;
stack<int> S;
int a[maxn];

void init(int n) {
    for (int i = 0; i <= n; i++) G[i].clear();
}

void dfs(int u) {
    pre[u] = lowlink[u] = ++dfs_clock;
    S.push(u);
    for (int i = 0; i < G[u].size(); i++) {
        int v = G[u][i];
        if (!pre[v]) {
            dfs(v);
            lowlink[u] = min(lowlink[u],lowlink[v]);
        }
        else if (!sccno[v]) {
            lowlink[u] = min(lowlink[u],pre[v]);
        }
    }
    if (lowlink[u] == pre[u]) {
        scc_cnt++;
        while (1) {
            int x = S.top();
            S.pop();
            sccno[x] = scc_cnt;
            if (x == u) break;
        }
    }
}

void find_scc(int n) {
    dfs_clock = scc_cnt = 0;
    CLR(sccno,0);
    CLR(pre,0);
    for (int i = 1; i <= n; i++) {
        if (!pre[i]) dfs(i);
    }
}

int out[maxn];
int cnt[maxn];

int main() {
    int n,m;
    //freopen("data.in","r",stdin);
    while (cin>>n>>m) {
        init(n);
        for (int i = 0; i < m; i++) {
            int a,b;
            scanf("%d%d",&a,&b);
            G[a].PB(b);
        }
        //for (int i = 0; i <= scc_cnt; i++) new_g[i].clear();
        find_scc(n);
        CLR(out,0);
        CLR(cnt,0);
        for (int i = 1; i <= n; i++) {
            cnt[sccno[i]]++;
            for (int j = 0; j < G[i].size(); j++) {
                int v = G[i][j];
                if (sccno[i] != sccno[v]) {
                    out[sccno[i]]++;
                }
            }
        }
        bool flag = true;
        int k = 0;
        for (int i = 1; i <= scc_cnt; i++) {
            if (k && !out[i]) {
                flag = false;
                break;
            }
            if (!out[i]) k = i;
        }
        if (flag) cout<<cnt[k]<<endl;
        else cout<<0<<endl;
    }
}

 4. HDU 3861 The King’s Problem

题目读完之后发现应该是最小路径覆盖,但是两个问题:数据范围和图有环。先强连通缩点,重新构图,这样图就变成了DAG,在应用Hungary算法就可以求出答案了。

#include <set>
#include <map>
#include <list>
#include <stack>
#include <queue>
#include <ctime>
#include <cmath>
#include <cstdio>
#include <vector>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

#pragma comment(linker, "/STACK:1024000000,1024000000")

#define     IT              iterator
#define     PB(x)           push_back(x)
#define     CLR(a,b)        memset(a,b,sizeof(a))

using namespace std;

typedef     long long               ll;
typedef     unsigned long long      ull;
typedef     vector<int>             vint;
typedef     vector<ll>              vll;
typedef     vector<ull>             vull;
typedef     set<int>                sint;
typedef     set<ull>                sull;

const int maxn = 50000 + 5;
vint G[maxn];
int pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,scc_cnt;
stack<int> S;
int a[maxn];

void init(int n) {
    for (int i = 0; i <= n; i++) G[i].clear();
}

void dfs(int u) {
    pre[u] = lowlink[u] = ++dfs_clock;
    S.push(u);
    for (int i = 0; i < G[u].size(); i++) {
        int v = G[u][i];
        if (!pre[v]) {
            dfs(v);
            lowlink[u] = min(lowlink[u],lowlink[v]);
        }
        else if (!sccno[v]) {
            lowlink[u] = min(lowlink[u],pre[v]);
        }
    }
    if (lowlink[u] == pre[u]) {
        scc_cnt++;
        while (1) {
            int x = S.top();
            S.pop();
            sccno[x] = scc_cnt;
            if (x == u) break;
        }
    }
}

void find_scc(int n) {
    dfs_clock = scc_cnt = 0;
    CLR(sccno,0);
    CLR(pre,0);
    for (int i = 1; i <= n; i++) {
        if (!pre[i]) dfs(i);
    }
}

vint new_g[maxn];
int match[maxn];
bool vis[maxn];

bool findpath(int u) {
    for (int i = 0; i < new_g[u].size(); i++) {
        int v = new_g[u][i];
        if (!vis[v]) {
            vis[v] = 1;
            if (match[v] == -1 || findpath(match[v])) {
                match[v] = u;
                return true;
            }
        }
    }
    return false;
}

int hungary() {
    int ans = 0;
    CLR(match,-1);
    for (int i = 1; i <= scc_cnt; i++) {
        CLR(vis,0);
        if (findpath(i)) ans++;
    }
    return ans;
}

int main() {
    //freopen("data.in","r",stdin);
    int n,m;
    int T;
    cin>>T;
    while (T--) {
        cin>>n>>m;
        init(n);
        for (int i = 0; i < m; i++) {
            int a,b;
            scanf("%d%d",&a,&b);
            G[a].PB(b);
        }
        //for (int i = 0; i <= scc_cnt; i++) new_g[i].clear();
        find_scc(n);
        for (int i = 0; i <= scc_cnt; i++) new_g[i].clear();
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j < G[i].size(); j++) {
                int v = G[i][j];
                if (sccno[i] != sccno[v]) {
                    new_g[sccno[i]].PB(sccno[v]);
                }
            }
        }
        cout<<scc_cnt - hungary()<<endl;
    }
}

 5. HDU 3639 Hawk-and-Chicken

开始还是老套路,先强连通缩点,需要注意的话这个题重新构图需要反向建边,然后对每个入度0的点DFS,求最大值即可。

#include <set>
#include <map>
#include <list>
#include <stack>
#include <queue>
#include <ctime>
#include <cmath>
#include <cstdio>
#include <vector>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

#pragma comment(linker, "/STACK:1024000000,1024000000")

#define     IT              iterator
#define     PB(x)           push_back(x)
#define     CLR(a,b)        memset(a,b,sizeof(a))

using namespace std;

typedef     long long               ll;
typedef     unsigned long long      ull;
typedef     vector<int>             vint;
typedef     vector<ll>              vll;
typedef     vector<ull>             vull;
typedef     set<int>                sint;
typedef     set<ull>                sull;

const int maxn = 5000 + 5;
vint G[maxn];
int pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,scc_cnt;
stack<int> S;
int a[maxn];

void init(int n) {
    for (int i = 0; i <= n; i++) G[i].clear();
}

void dfs(int u) {
    pre[u] = lowlink[u] = ++dfs_clock;
    S.push(u);
    for (int i = 0; i < G[u].size(); i++) {
        int v = G[u][i];
        if (!pre[v]) {
            dfs(v);
            lowlink[u] = min(lowlink[u],lowlink[v]);
        }
        else if (!sccno[v]) {
            lowlink[u] = min(lowlink[u],pre[v]);
        }
    }
    if (lowlink[u] == pre[u]) {
        scc_cnt++;
        while (1) {
            int x = S.top();
            S.pop();
            sccno[x] = scc_cnt;
            if (x == u) break;
        }
    }
}

void find_scc(int n) {
    dfs_clock = scc_cnt = 0;
    CLR(sccno,0);
    CLR(pre,0);
    for (int i = 0; i < n; i++) {
        if (!pre[i]) dfs(i);
    }
}

vint new_g[maxn];
int rec[maxn];
int out[maxn];
int lab[maxn];
bool vis[maxn];
int cnt;

int dp(int u) {
    vis[u] = true;
    cnt += lab[u];
    for (int i = 0; i < new_g[u].size(); i++) {
        int v = new_g[u][i];
        if (!vis[v]) {
            dp(v);
        }
    }
    return cnt;
}

int main() {
    //freopen("data.in","r",stdin);
    int n,m;
    int T;
    cin>>T;
    for (int t = 1; t <= T; t++) {
        cin>>n>>m;
        init(n);
        for (int i = 0; i < m; i++) {
            int a,b;
            scanf("%d%d",&a,&b);
            G[a].PB(b);
        }
        find_scc(n);
        CLR(out,0);
        CLR(lab,0);
        for (int i = 0; i <= scc_cnt; i++) new_g[i].clear();
        for (int i = 0; i < n; i++) {
            lab[sccno[i]]++;
            for (int j = 0; j < G[i].size(); j++) {
                int v = G[i][j];
                if (sccno[i] != sccno[v]) {
                    new_g[sccno[v]].PB(sccno[i]);
                    out[sccno[i]]++;
                }
            }
        }
        CLR(rec,0);
        int ans = 0;
        for (int i = 1; i <= scc_cnt; i++) {
            if (!out[i]) {
                CLR(vis,0);
                cnt = 0;
                rec[i] = dp(i);
                ans = max(ans,rec[i]);
            }
        }
        /*for (int i = 0; i < n; i++) {
            cout<<sccno[i]<<" ";
        }
        cout<<endl;
        for (int i = 1; i <= scc_cnt; i++) {
            cout<<rec[i][0]<<" "<<rec[i][1]<<endl;
        }*/
        printf("Case %d: %d\n",t,ans - 1);
        bool flag = false;
        for (int i = 0; i < n; i++) {
            if (rec[sccno[i]] == ans) {
                if (flag) printf(" %d",i);
                else {
                    printf("%d",i);
                    flag = true;
                }
            }
        }
        printf("\n");
    }
}

 6. HDU 2242 考研路茫茫――空调教室

题目很好理解,给出了无向图,断开一条边使得分成的两个部分人数差最小。开始先用tarjan求一下边双联通,确定这个图当中桥有哪些,答案就是这些桥中的一个。然后对于缩完点的图,应该是一棵树,这样的话就可以利用DFS的性质,对这一棵树DFS一遍,就可以求出人数差了。

#include <set>
#include <map>
#include <list>
#include <stack>
#include <queue>
#include <ctime>
#include <cmath>
#include <cstdio>
#include <vector>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

#pragma comment(linker, "/STACK:1024000000,1024000000")

#define     IT              iterator
#define     PB(x)           push_back(x)
#define     CLR(a,b)        memset(a,b,sizeof(a))

using namespace std;

typedef     long long               ll;
typedef     unsigned long long      ull;
typedef     vector<int>             vint;
typedef     vector<ll>              vll;
typedef     vector<ull>             vull;
typedef     set<int>                sint;
typedef     set<ull>                sull;

const int maxn = 20000 + 5;
struct Edge {
    int to,next;
    bool cut;
    bool cong;
};
stack<int> S;
const int maxm = 40000 + 5;
Edge edge[maxm];
int head[maxn],tot;
int low[maxn],dfn[maxn],belong[maxn];
int Index;
int block;
bool Instack[maxn];
int bridge;
int peo[maxn];
int tpe[maxn];

void addedge(int u,int v) {
    edge[tot].to = v;
    edge[tot].next = head[u];
    edge[tot].cut = false;
    edge[tot].cong = false;
    head[u] = tot++;
}

void tarjan(int u,int pre,bool ff) {
    int v;
    low[u] = dfn[u] = ++Index;
    S.push(u);
    Instack[u] = true;
    for (int i = head[u]; i != -1; i = edge[i].next) {
        v = edge[i].to;
        if (v == pre && (!ff)) continue;
        if (!dfn[v]) {
            tarjan(v,u,edge[i].cong);
            if (low[u] > low[v]) low[u] = low[v];
            if (low[v] > dfn[u]) {
                bridge++;
                edge[i].cut = true;
                edge[i^1].cut = true;
            }
        }
        else if (Instack[v] && low[u] > dfn[v]) {
            low[u] = dfn[v];
        }
    }
    if (low[u] == dfn[u]) {
        block++;
        do {
            v = S.top();
            S.pop();
            Instack[v] = false;
            belong[v] = block;
        }while (v != u);
    }
}

void init() {
    tot = 0;
    CLR(head,-1);
    while (!S.empty()) S.pop();
    CLR(tpe,0);
}

int sum = 0;
map<ll,int> edgelab;
vint g[maxn];
int minans;

int dfs(int u,int pre) {
    int ans = tpe[u];
    for (int i = 0; i < g[u].size(); i++) {
        if (g[u][i] == pre) continue;
        ans += dfs(g[u][i],u);
    }
    //cout<<ans<<endl;
    minans = min(minans,abs(sum - 2 * ans));
    return ans;
}

int main() {
    //freopen("data.in","r",stdin);
    //freopen("data.out","w",stdout);
    int n,m;
    while (cin>>n>>m) {
        init();
        sum = 0;
        edgelab.clear();
        for (int i = 1; i <= n; i++) {
            scanf("%d",peo+i);
            sum += peo[i];
        }
        for (int i = 0; i < m; i++) {
            int a,b;
            scanf("%d%d",&a,&b);
            a++;b++;
            if (a < b) swap(a,b);
            ll tmp = a * 100000 + b;
            if (edgelab.find(tmp) != edgelab.end()) {
                int lab = edgelab[tmp];
                edge[lab].cong = true;
                edge[lab^1].cong = true;
            }
            else {
                edgelab[tmp] = tot;
                addedge(a,b);
                addedge(b,a);
            }
        }
        CLR(dfn,0);
        CLR(Instack,false);
        Index = block = 0;
        tarjan(1,0,false);
        if (block == 1) {
            cout<<"impossible"<<endl;
            continue;
        }
        for (int i = 0; i <= block; i++) g[i].clear();
        minans = 0x3f3f3f3f;
        for (int i = 1; i <= n; i++) {
            for (int j = head[i]; j != -1; j = edge[j].next) {
                if (edge[j].cut) {
                    g[belong[i]].PB(belong[edge[j].to]);
                }
            }
        }
        //for (int i = 1; i <= n; i++) cout<<belong[i]<<endl;
        for (int i = 1; i <= n; i++) tpe[belong[i]] += peo[i];
        dfs(1,0);
        cout<<minans<<endl;
    }
}

 7. HDU 3849 By Recognizing These Guys, We Find Social Networks Useful

先对顶点进行哈希,然后找到图中的桥,输出出来就行了。需要注意的是,如果图不是连通图的,是不存在桥的概念的,所以缩点之后需要判一下图连通性。

#include <set>
#include <map>
#include <list>
#include <stack>
#include <queue>
#include <ctime>
#include <cmath>
#include <cstdio>
#include <vector>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

#pragma comment(linker, "/STACK:1024000000,1024000000")

#define     IT              iterator
#define     PB(x)           push_back(x)
#define     CLR(a,b)        memset(a,b,sizeof(a))

using namespace std;

typedef     long long               ll;
typedef     unsigned long long      ull;
typedef     vector<int>             vint;
typedef     vector<ll>              vll;
typedef     vector<ull>             vull;
typedef     set<int>                sint;
typedef     set<ull>                sull;

struct Edge {
    int to,next;
    bool cut;//是否是桥
    bool cong;//判断重边
};

const int maxn = 20000 + 5;
const int maxm = 200000 + 5;
Edge edge[maxm];
int head[maxn],tot;
int low[maxn],dfn[maxn],Stack[maxn],belong[maxn];
int Index,top;
int block;
bool Instack[maxn];
int bridge;
int n,m;
map<string,int> has;
map<int,string> fas;

void addedge(int u,int v,int tt) {
    edge[tot].to = v;
    edge[tot].next = head[u];
    edge[tot].cut = false;
    edge[tot].cong = tt;
    head[u] = tot++;
}

void tarjan(int u,int pre) {
    int v;
    low[u] = dfn[u] = ++Index;
    Stack[top++] = u;
    Instack[u] = true;
    for (int i = head[u]; i != -1; i = edge[i].next) {
        v = edge[i].to;
        if (v == pre) continue;
        if (!dfn[v]) {
            tarjan(v,u);
            if (low[u] > low[v]) low[u] = low[v];
            if (low[v] > dfn[u]) {
                bridge++;
                edge[i].cut = true;
                edge[i^1].cut = true;
            }
        }
        else if (Instack[v] && low[u] > dfn[v]) {
            low[u] = dfn[v];
        }
    }
    if (low[u] == dfn[u]) {
        block++;
        do {
            v = Stack[--top];
            Instack[v] = false;
            belong[v] = block;
        } while (v != u);
    }
}

int fa[maxn];

void init() {
    tot = 0;
    for (int i = 0; i < maxn; i++) fa[i] = i;
    has.clear();
    fas.clear();
    CLR(head,-1);
}

int getf(int x) {
    if (fa[x] == x) return x;
    else return fa[x] = getf(fa[x]);
}

void unit(int x,int y) {
    x = getf(x);
    y = getf(y);
    fa[x] = y;
}

int main() {
    int T;
    cin>>T;
    while (T--) {
        scanf("%d%d",&n,&m);
        init();
        int cnt = 1;
        for (int i = 0; i < m; i++) {
            char s1[20],s2[20];
            scanf("%s%s",s1,s2);
            string tmpa(s1);
            string tmpb(s2);
            int a,b;
            if (has.count(tmpa)) a = has[tmpa];
            else {
                has[tmpa] = a = cnt++;
                fas[a] = tmpa;
            }
            if (has.count(tmpb)) b = has[tmpb];
            else {
                has[tmpb] = b = cnt++;
                fas[b] = tmpb;
            }
            unit(a,b);
            addedge(a,b,true);
            addedge(b,a,false);
        }
        CLR(dfn,0);
        CLR(Instack,false);
        Index = top = block = 0;
        tarjan(1,0);
        int tmp = 0;
        for (int i = 1; i <= n; i++) {
            if (fa[i] == i) tmp++;
        }
        if (tmp == 1) {
            printf("%d\n",block-1);
            for (int i = 1; i <= n; i++) {
                for (int j = head[i]; j != -1; j = edge[j].next) {
                    if (edge[j].cut && edge[j].cong) {
                        printf("%s %s\n",fas[i].c_str(),fas[edge[j].to].c_str());
                    }
                }
            }
        }
        else printf("0\n");
    }
}

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!