hdu3394--Railway(點的雙連通份量)

一個公園中有 n 個景點,景點之間經過無向的道路來鏈接(明顯的點雙ios

),若是至少兩個環公用一條路,路上的遊客就會發生衝突;若是一條路不屬於任何的環,這條路就不必修ide

問,有多少路沒必要修,有多少路會發生衝突spa

每個連通塊中,若是邊數大於點數,這個塊中全部的邊所有是衝突邊。string

全部橋爲不須要修建的路。it

 

點雙連通份量:對於一個連通圖,若是任意兩點至少存在兩條「點不重複」的路徑,則說這個圖是點雙連通的(通常簡稱雙連通),簡單來講就是任意兩條邊都在同一個簡單環中,即內部無割頂。
多餘邊:不在任何環中,必定是橋。io

衝突邊:若是一個環內的邊數大於點數,那麼這個環內全部邊都是「衝突邊」。

class

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
#include <stack>
using namespace std;
typedef long long ll;
#define cls(s,h) memset(s,h,sizeof s)
const int maxn = 1e5 + 7;
int n , m ;
int tot;
struct  edge
{
    int to,from,nxt;
}e[maxn << 1];

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

int dfn[maxn],low[maxn],idx;
stack<edge> stk;
set<int> bcc;
int cut; //brige
int ans; //the outway brige
int flag;
void tanjan(int u , int pre){
    dfn[u] = low[u] = ++idx;
    for(int i = head[u]; ~i;i = e[i].nxt){
        int v = e[i].to;
        if(v == pre) continue;
        if(!dfn[v]){
            stk.push(e[i]);
            tanjan(v,u);
            low[u] = min(low[u],low[v]);
            if(low[v] >= dfn[u]){//割點
                edge tmp;
                int cnt = 0;
                bcc.clear();
                //bcc[++flag].push(e[i]);
                do{//找v.DCC的子集
                    cnt++;//子集的邊數
                    tmp = stk.top();
                    stk.pop();
                    //點數
                    bcc.insert(tmp.from);
                    bcc.insert(tmp.to);
                }while(tmp.from != u || tmp.to != v);
                if(cnt > bcc.size()) ans += cnt;
               // flag ++;
            }
            if(low[v] > dfn[u]) ++cut;
        }else if(dfn[v] < dfn[u]){
            stk.push(e[i]);
            low[u] = min(low[u],dfn[v]);
        }
    }
}

void init(){
    cls(head,-1);
    cls(dfn,0);
    flag = ans = cut = tot = idx = 0;
}

int main(int argc, char const *argv[])
{
    while(scanf("%d %d",&n,&m) && n + m){
        int u , v;
        init();
        for(int i = 1;i <= m ;i ++){
            scanf("%d %d",&u,&v);
            add_edge(u,v);
            add_edge(v,u);
        }
        for(int i = 1;i <= n;i ++){
            if(!dfn[i]) tanjan(i,-1);
        }
        printf("%d %d\n",cut,ans );
    }
    return 0;
}
View Code

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
#include <stack>
using namespace std;
typedef long long ll;
#define cls(s,h) memset(s,h,sizeof s)
const int maxn = 1e5 + 7;
int n , m ;
int tot;
struct  edge
{
    int to,from,nxt;
}e[maxn << 1];

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

int dfn[maxn],low[maxn],idx;
stack<edge> stk;
set<int> bcc;
int cut; //brige 橋
int ans; //the outway brige 衝突的邊
int flag;
void tanjan(int u , int pre){
    dfn[u] = low[u] = ++idx;
    for(int i = head[u]; ~i;i = e[i].nxt){
        int v = e[i].to;
        if(v == pre) continue;
        if(!dfn[v]){
            stk.push(e[i]);
            tanjan(v,u);
            low[u] = min(low[u],low[v]);
            if(low[v] >= dfn[u]){//割點 割點斷定法則
                edge tmp;
                int cnt = 0;
                bcc.clear();
                //bcc[++flag].push(e[i]);
                do{//找v.DCC的子集
                    cnt++;//子集的邊數
                    tmp = stk.top();
                    stk.pop();
                    //點數
                    bcc.insert(tmp.from);
                    bcc.insert(tmp.to);
                }while(tmp.from != u || tmp.to != v);
                if(cnt > bcc.size()) ans += cnt;
               // flag ++;
            }
            if(low[v] > dfn[u]) ++cut;
        }else if(dfn[v] < dfn[u]){
            stk.push(e[i]);
            low[u] = min(low[u],dfn[v]);
        }
    }
}

void init(){
    cls(head,-1);
    cls(dfn,0);
    flag = ans = cut = tot = idx = 0;
}

int main(int argc, char const *argv[])
{
    while(scanf("%d %d",&n,&m) && n + m){
        int u , v;
        init();
        for(int i = 1;i <= m ;i ++){
            scanf("%d %d",&u,&v);
            add_edge(u,v);
            add_edge(v,u);
        }
        for(int i = 1;i <= n;i ++){
            if(!dfn[i]) tanjan(i,-1);
        }
        printf("%d %d\n",cut,ans );
    }
    return 0;
}
更新
相關文章
相關標籤/搜索