POJ 3352 Road Construction&& POJ 3177 Redundant Paths 双联通分量

来源:互联网 发布:淘宝众筹怎么找不到了 编辑:程序博客网 时间:2024/06/06 05:02

大意:给定n点,和m条边的关系图中的一些边随时可能施工导致不能够通过,所以至少加多少条边才能够使得途中任意两条边联通?


思路:很明显只要图中的任意两点都是两条边来链接即可。那么我们可以先缩点构建新图,然后统计出度为1的点的个数ans,那么需要加的边数就是(ans+1)/2条;

(PS;因为建图是双向的图所以,在Tarjan缩点的时候就需要遇到临边便越过,并且判断是不是同一个联通分支用num比较!)


#include<map>#include<queue>#include<cmath>#include<cstdio>#include<stack>#include<iostream>#include<cstring>#include<algorithm>#define LL int#define inf 0x3f3f3f3f#define eps 1e-8#include<vector>#define ls l,mid,rt<<1#define rs mid+1,r,rt<<1|1using namespace std;int n,m;const int Ma = 1000005;int head[Ma],dfn[Ma],num[Ma],du[Ma],stk[Ma],vis[Ma],low[Ma];int cnt,top,time,css;bool mp[5100][5100];struct node{    int to,next;}q[Ma];void bu(int a,int b){    q[cnt].to = b;    q[cnt].next = head[a];    head[a] = cnt++;}void init(){    time = 1;    css = top = cnt = 0;    memset(dfn,0,sizeof(dfn));    memset(low,0,sizeof(low));    memset(vis,0,sizeof(vis));    memset(head,-1,sizeof(head));    memset(num,0,sizeof(num));    memset(du,0,sizeof(du));    memset(mp,false,sizeof(mp));}void Tarjan(int u,int To){    low[u] = dfn[u] = time++;    vis[u] = 1;    stk[top++] = u;    for(int i = head[u]; ~i ; i = q[i].next){        int v = q[i].to;        if(i == (To^1)) continue;        if(!vis[v]){            Tarjan(v,i);            low[u] = min(low[u],low[v]);        }        else            low[u] = min(low[u],dfn[v]);    }    if(low[u] == dfn[u]){//找到极大联通分量        css++;        while(top > 0&&stk[top] != u){            top --;            vis[stk[top] ] = 2;            num[stk[top] ] = css;        }    }}int main(){    int k,i,j,a,b;    while(~scanf("%d%d",&n,&m)){        init();        for(i = 0;i < m;++ i){            scanf("%d%d",&a,&b);//////注意重边的问题!            if(mp[a][b]){                continue;            }            mp[a][b] = mp[b][a] = true;            bu(a,b);            bu(b,a);        }        Tarjan(1,-1);        for(i = 1;i <= n;++ i)            for(j = head[i]; ~j ;j = q[j].next)                if( num[i] != num[q[j].to] )                    du[num[i] ]++;        int ans = 0;        for(i = 1;i <= n;++ i)            if(du[i] == 1)                ans++;        printf("%d\n",(ans+1)>>1);    }    return 0;}


0 0
原创粉丝点击