hdu4612Warm up(双联通缩点+树直径)

来源:互联网 发布:人工智能概念股及代码 编辑:程序博客网 时间:2024/06/15 01:23

借鉴这里:http://blog.csdn.net/softshell/article/details/9496161

有N个点,M条边(有重边)的无向图,这样图中会可能有桥,问加一条边后,使桥最少,求最少桥的数量。 

缩点后,求出图中的桥的个数,然后重建图必为树,求出树的最长直径,在该直径的两端点连一边,则图中的桥会最少。

双联通缩点有很多不懂滴地方。。。不咋明白。。。问题之一。。vis数组用不用写。。唉。。唉。。

#pragma comment(linker, "/STACK:1024000000,1024000000")#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<queue>using namespace std;#define clr(x) memset(x,0,sizeof(x))#define maxn 300015#define maxm 4000015struct node{    int to,next;}e[maxm],e2[maxm];int head[maxn],tot;int head2[maxn],tot2;int col[maxn],dfn[maxn],low[maxn],sta[maxn];int top,ti,scc;  //scc 双联通分支个数int n,m;bool vis[maxn];void init(){    memset(head,-1,sizeof(head));    clr(vis);    clr(dfn);    tot=0;    top=0;    scc=ti=0;}void add(int u,int v){    e[tot].to=v;    e[tot].next=head[u];    head[u]=tot++;}void add2(int u,int v){    e2[tot2].to=v;    e2[tot2].next=head2[u];    head2[u]=tot2++;}void tarjan(int u,int fa){    dfn[u]=low[u]=++ti;    sta[++top]=u;    vis[u]=true;    int cnt=0;    for(int i=head[u];i!=-1;i=e[i].next){        int v=e[i].to;        if(!dfn[v]){            tarjan(v,u);            low[u]=min(low[u],low[v]);        }        else if(fa==v){            if (cnt) low[u] = min(low[u],dfn[v]);//重边            cnt++;        }        else if(vis[v])low[u]=min(low[u],dfn[v]);    }    if(dfn[u]==low[u]){        int x;        scc++;        do{            x = sta[top--];            vis[x]=false;            col[x] = scc;        }while(x!=u);    }}void build(){    tot2 = 0;    memset(head2,-1,sizeof(head2));    for(int i = 1; i <= n; i++){        for(int j = head[i]; j!=-1; j = e[j].next){            int v = e[j].to;            if(col[i]!=col[v])                add2(col[i],col[v]);        }    }}int r;//直径int bfs(int x){    queue<int>q;    int dis[maxn];    int end;    memset(dis,-1,sizeof(dis));    q.push(x);    dis[x]=0;    while(!q.empty()){        int u=q.front();        q.pop();        r=dis[u];        end=u;        for(int i=head2[u];i!=-1;i=e2[i].next){            int v=e2[i].to;            if(dis[v]==-1){                dis[v]=dis[u]+1;                q.push(v);            }        }    }    return end;}int main(){    int u,v;    while(scanf("%d%d",&n,&m)!=EOF){        init();        if(n==0&&m==0)break;        for(int i=0;i<m;i++){            scanf("%d%d",&u,&v);            if(v==u)continue;            add(u,v);            add(v,u);        }        tarjan(1,-1);        build();        r=0;        bfs(bfs(1));        printf("%d\n",scc-r-1);    }    return 0;}

 

原创粉丝点击