UVALive 4287 - Proving Equivalences(强连通分量)

来源:互联网 发布:制作图文的软件 编辑:程序博客网 时间:2024/06/05 17:28

题目:

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=72618#problem/C

题意:

给出n个节点的m条边的有向图,要求添加最少的边使得新的图强连通.

思路:

强连通的部分敲模版即可.找出强连通分量,将每一个强连通缩成点, 得到一个新的有向图,然后求出有a个节点的入度为0, b个节点的出度为0, 答案便是a, b的最大值.

一开始不懂这样的思路, 其实画个图就可以知道了.

AC.

#include <iostream>#include <cstdio>#include <cstring>#include <stack>#include <vector>using namespace std;const int MAX = 5e4+5;vector<int> G[MAX];int pre[MAX], lowlink[MAX], sccno[MAX], dfs_clock, scc_cnt;stack<int> S;int in0[MAX], out0[MAX];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;    memset(sccno, 0, sizeof(sccno));    memset(pre, 0, sizeof(pre));    for(int i = 0; i < n; ++i) {        if(!pre[i]) dfs(i);    }}int main(){//freopen("in", "r", stdin);    int T;    scanf("%d", &T);    while(T--) {        int n, m;        for(int i = 0; i < n; ++i) G[i].clear();        scanf("%d %d", &n, &m);        for(int i = 0; i < m; ++i) {            int u, v;            scanf("%d %d", &u, &v);            u--; v--;            G[u].push_back(v);        }        find_scc(n);        memset(in0, 0, sizeof(in0));        memset(out0, 0, sizeof(out0));        for(int u = 0; u < n; ++u) {            for(int i = 0; i < G[u].size(); ++i) {                int v = G[u][i];                if(sccno[u] != sccno[v]) {                    in0[sccno[v]] = out0[sccno[u]] = 1;                }            }        }        int a = 0, b = 0;        for(int i = 1; i <= scc_cnt; ++i) {            if(!in0[i]) a++;            if(!out0[i]) b++;        }        int ans = max(a, b);        if(scc_cnt == 1) ans = 0;        printf("%d\n", ans);    }    return 0;}



0 0
原创粉丝点击