POJ - 1236 Network of Schools 【有向图至少加多少条边变成强联通图】

传送门
//题意: 给定一幅有向图, 问:
1: 至少需要给几个人传递消息, 可以使图中任意点可以收到消息.
2: 至少加多少条边, 使得原图变成一幅强联通图.
//思路: 这个就很简单了, 就是一个水题. 随便分析一下就知道了. 对应答案就是缩完点后的图中入度为0的点数, max(入度为0的点数, 初度为0的点数). 注意一个坑点就是当缩完点后只有一个点时, 需要特判答案.

AC Code

/** @Cain*/
const int maxn = 1e2+5;
int dfn[maxn],low[maxn],bel[maxn];
int in[maxn],out[maxn];
int dfs_id,cnt;
vector<int>G[maxn];
stack<int >st;
void tarjan(int u){
    dfn[u] = low[u] = ++dfs_id;
    st.push(u);
    for(int i=0; iint v = G[u][i];
        //if(v == fa) continue;
        if(!dfn[v]){
            tarjan(v);
            low[u] = min(low[u],low[v]);
        }
        else if(!bel[v])
            low[u] = min(low[u],dfn[v]);
    }
    if(low[u] == dfn[u]){
        cnt++;
        while(1){
            int v = st.top();
            st.pop();
            bel[v] = cnt;
            if(v == u) break;
        }
    }
}

void solve()
{
    int n;
    while(~scanf("%d",&n)){
        Fill(dfn,0); Fill(low,0);
        Fill(bel,0); Fill(in,0); Fill(out,0);
        dfs_id = cnt = 0;
        for(int i=1;i<=n;i++) G[i].clear();
        for(int i=1;i<=n;i++){
            while(1){
                int u ; scanf("%d",&u);
                if(u == 0) break;
                G[i].push_back(u);
            }
        }
        for(int i=1;i<=n;i++){
            if(!dfn[i]) tarjan(i);
        }
        for(int i=1;i<=n;i++){
            for(int j=0;jint v = G[i][j];
                if(bel[i] != bel[v]){
                    in[bel[v]]++;
                    out[bel[i]]++;
                }
            }
        }
        if(cnt == 1){
            printf("1\n0\n");
            continue;
        }
        int cnt1 = 0 ,cnt2 = 0;
        for(int i=1;i<=cnt;i++){
            if(!in[i]) cnt1++;
            if(!out[i]) cnt2++;
        }
        printf("%d\n%d\n",cnt1,max(cnt1,cnt2));
    }
}

你可能感兴趣的:(强联通_点边双联通_桥割点)