SSummerZzz kuangbin專題 專題九 連通圖 POJ 3177 Redundant Paths

題目連接:https://vjudge.net/article/371?tdsourcetag=s_pcqq_aiomsgnode

題目:給定一個連通圖,題目說,任意兩個點至少有一條路線能夠相互到達,ios

爲保證任意兩點有徹底不一樣的路線(點能夠相同,邊不能相同)能夠相互到達至少須要加幾條邊。ui

思路:tarjan縮點,以後重構圖,找出度數爲1的scc個數scc_cnt,這些點相互鏈接,答案能夠得出是 (scc_cnt+1)/2。spa

兩組樣例:.net

n = 5 ,m = 4  |  (1 2)  (1 3) )(1 4) (1 5)code

n = 8, m = 9  | (1 2) (1 4) (2 3) (3 4) (4 5) (5 6) (6 7) (5 8) (7 8 )blog

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

const int N = (int)5e3+10;
int head[N],dfn[N],low[N],scc_no[N],s[N],du[N];
int n,m,tot,tim,scc,top;
struct node{
    int to;
    int nxt;
}e[N << 2];

inline void add(int u,int v){
    e[tot].to = v;
    e[tot].nxt = head[u];
    head[u] = tot++;
}

void tarjan(int now,int pre){
    dfn[now] = low[now] = ++tim;
    s[top++] = now;
    
    //這裏有狀況,兩點之間可能>1條路直接鏈接
    //因此,須要處理下邊的重複問題
    int to,pre_cnt = 0;
    for(int o = head[now]; ~o; o = e[o].nxt){
        to = e[o].to;
        //只是一條無向邊,處理一下
        if(to == pre && pre_cnt == 0){
            pre_cnt = 1;
            continue;
        }
        if(!dfn[to]){
            tarjan(to,now);
            low[now] = min(low[now],low[to]);
        }
        else low[now] = min(low[now],dfn[to]);
    }

    if(dfn[now] == low[now]){
        ++scc;
        int x;
        do{
            x = s[--top];
            scc_no[x] = scc;
        }while(now != x);
    }
}

void rebuild(){
    int to;
    for(int now = 1; now <= n; ++now){
        for(int o = head[now]; ~o; o = e[o].nxt){
           to = e[o].to;
           if(scc_no[now] != scc_no[to]){
                ++du[scc_no[now]];
                ++du[scc_no[to]];
           }
        }
    }
}

void solve(){
    int p = 0;
 //   cout << scc << endl;
 
    //度數爲何是2的,由於是無向圖,其實除2就是度數爲1了
    for(int i = 1; i <= scc; ++i)
        if(du[i] == 2) ++p;
  //  cout << p << endl;

    printf("%d\n",(p+1)/2);
}

int main(){

    int u,v;
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n; ++i) head[i] = -1;
    for(int i = 0; i < m; ++i){
        scanf("%d%d",&u,&v);
        add(u,v); add(v,u);
    }
    tarjan(1,1);
    rebuild();
    solve();

    return 0;
}
相關文章
相關標籤/搜索