POJ3177:Redundant Paths——题解

http://poj.org/problem?id=3177

明显要求桥的一道题。

(因为有桥就说明只能从那一条路走,换句话说就是只有一种方法)

求完桥后按照结论(加几条边成双连通图的结论,不会请baidu)就可以输出ans啦!

(为此学了一下新的桥的求法……原来的那个常数太大了)

#include<stack>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
inline int read(){
    int x=0,w=1;char ch=0;
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    return x*w;
}
const int maxn=5001;
int cnt=1,head[maxn];
struct node{
    int w;
    int ed;
    int nxt;
    int st;
}edge[20001];
void add(int u,int v){
    cnt++;
    edge[cnt].ed=v;
    edge[cnt].st=u;
    edge[cnt].nxt=head[u];
    head[u]=cnt;
    return;
}
bool bridge[20001];
int dfn[maxn];
int low[maxn];
bool instack[maxn];
int fa[maxn];
int from[maxn];
int indeg[maxn];
int t=0;
void tarjan(int u){
    t++;
    dfn[u]=t;
    low[u]=t;
    for(int i=head[u];i;i=edge[i].nxt){
    if(i==(from[u]^1))continue;
    int v=edge[i].ed;
    if(!dfn[v]){
        from[v]=i;
        tarjan(v);
        low[u]=min(low[u],low[v]);
        if(low[v]>dfn[u])bridge[from[v]]=bridge[from[v]^1]=1;
    }else{
        low[u]=min(low[u],dfn[v]);
    }
    }
    return;
}
int find(int a){
    if(fa[a]==a)return a;
    return fa[a]=find(fa[a]);
}
int main(){
    int f=read();
    int r=read();
    for(int i=1;i<=r;i++){
    int u=read();
    int v=read();
    add(u,v);
    add(v,u);
    }
    tarjan(1);
    for(int i=1;i<=f;i++)fa[i]=i;
    for(int i=2;i<=cnt;i+=2){
    if(!bridge[i])fa[find(edge[i].st)]=find(edge[i].ed);
    }
    for(int i=2;i<=cnt;i+=2){
    if(bridge[i])indeg[find(edge[i].st)]++,indeg[find(edge[i].ed)]++;
    }
    int leaf=0;
    for(int i=1;i<=f;i++){
    if(find(i)==i){
        if(indeg[i]==1)leaf++;
    }
    }
    printf("%d\n",(leaf+1)/2);
    return 0;
}

 

posted @ 2017-11-16 19:09  luyouqi233  阅读(211)  评论(0编辑  收藏  举报