HDU4612

来源:互联网 发布:淘宝网登陆页 编辑:程序博客网 时间:2024/04/30 08:39

题意:一个连通图,求添加一条边,使桥的数目最小

分析:tarjan求连通,缩点,因为是双向边,所以需要做一下标记,缩点之后重新构图,新的图必定是树,求树的直径,

添加一条边之后能使树的直径上的桥去掉,所以剩下桥的个数为原图中桥的个数减去树的直径。


在tarjan过程中求桥的个数,当dfn[u]<low[v]时,说明从点u到v之后不能再通过其他边访问到u,证明边u-v是桥


#include <iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#include<stack>#define M 2000005#define N 200005#include<queue>#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;struct edge{    int u,next,in_bridge;}e[M];struct node {    int x,step;};vector<int> v[N];stack<int> s;int vis[N],c,n,ans,cnt,index,head[N],low[N],dfn[N],instack[N],id[N],bridge;void init(){    for(int i=1;i<=n;i++){        head[i]=-1;        dfn[i]=low[i]=0;        instack[i]=0;        v[i].clear();    }    while(!s.empty())    s.pop();    cnt=0;    index=0;    c=0;    ans=0;    bridge=0;}void addedge(int x,int y){      e[c].in_bridge=0;e[c].u=y;e[c].next=head[x];head[x]=c++;    e[c].in_bridge=0;e[c].u=x;e[c].next=head[y];head[y]=c++;}void tarjan(int u,int pre){   int flag=1;    low[u]=dfn[u]=++index;    instack[u]=1;    s.push(u);    int i,x;    for(i=head[u];i!=-1;i=e[i].next){        x=e[i].u;        if(x==pre&&flag){            flag=0;            continue;        }        if(!dfn[x]){            tarjan(x,u);            low[u]=min(low[u],low[x]);            if(dfn[u]<low[x]){                bridge++;                e[i].in_bridge=1;                e[i^1].in_bridge=1;            }        }else if(instack[x]){            low[u]=min(low[u],dfn[x]);        }    }    if(dfn[u]==low[u]){        ++cnt;        do{            x=s.top();            s.pop();            id[x]=cnt;            instack[x]=0;        }while(u!=x);    }}int bfs(int u){    queue<node> q;    node now,next;     memset(vis,0,sizeof(vis));    now.step=0,now.x=u;    q.push(now);    vis[u]=1;    int mark=u;    while(!q.empty()){        now=q.front();        q.pop();        if(now.step>ans){            ans=now.step;            mark=now.x;        }        int u=now.x;        next.step=now.step+1;        for(int i=v[u].size()-1;i>=0;i--){            next.x=v[u][i];            if(!vis[next.x]){                vis[next.x]=1;                q.push(next);            }        }    }    return mark;}int main(){    int m,i,j,x,y;    while(~scanf("%d%d",&n,&m)){        if(!n&&!m)        break;        init();        for(i=0;i<m;i++){            scanf("%d%d",&x,&y);            addedge(x,y);        }        tarjan(1,0);        for(i=1;i<=n;i++){            for(j=head[i];j!=-1;j=e[j].next){                x=i;y=e[j].u;                if(e[j].in_bridge){                    v[id[x]].push_back(id[y]);                }            }        }        x=bfs(1);        y=bfs(x);        printf("%d\n",bridge-ans);    }    return 0;}


0 0