poj3177 双连通分量

来源:互联网 发布:大数据舆情分析是什么 编辑:程序博客网 时间:2024/04/30 07:23

无向图,存成有向图,一条边存成两条

强连通的时候就会导致重边形成环,用fa记录来自的边,注意并且用flag判断是否只有一条那样的反向边

求需要添多少条边成双连通,记度为1的强连通分量数为ans,结果为( ans + 1 ) / 2

#include <iostream>#include<stdio.h>#include<cstring>#include<algorithm>using namespace std;#define maxn 5000+5#define FOR(i,j,k) for(int i=j;i<=k;i++)struct edge{    int from,to,next;}edge[5005*5005];int chu[maxn],ru[maxn];//强连通分量的出度,入度int dfn[maxn];//时间戳,dfs前访问到该点和dfs后访问该点int low[maxn];//该点及其后代能连回的最早祖先值int vis[maxn],stack[maxn],head[maxn],ans[maxn];int belong[maxn];//每个点属于几号分量int n;int tot;//一共多少条边int cnt;//一共多少分量int times,top;void init(){    tot=0,cnt=0,times=0,top=0;    memset(head,-1,sizeof(head));    memset(dfn,0,sizeof(dfn));    memset(low,0,sizeof(low));    memset(belong,0,sizeof(belong));    memset(chu,0,sizeof(chu));    memset(ru,0,sizeof(ru));    memset(vis,0,sizeof(vis));    memset(stack,0,sizeof(stack));    memset(ans,0,sizeof(ans));}void addedge(int from,int to){    tot++;    edge[tot].from=from;    edge[tot].to=to;    edge[tot].next=head[from];    head[from]=tot;}void tarjan(int u,int fa){    bool flag=false;    int v,i;    times++;    top++;    dfn[u]=low[u]=times;    vis[u]=1;    stack[top]=u;    for (i=head[u];i!=-1;i=edge[i].next)    {        v=edge[i].to;        if(v==fa && flag==0) {            flag=true;            continue;        }        if (vis[v]==0)        {            tarjan(v,u);            low[u]=min(low[u],low[v]);        }        if (vis[v]==1)            low[u]=min(low[u],dfn[v]);    }    if (dfn[u]==low[u])    {        cnt++;        while(1)        {            v=stack[top];            belong[v]=cnt;            vis[v]=2;            top--;            if(u==v) break;        }    }}int main(){    int n,m;    while(~scanf("%d%d",&n,&m)){        init();        while(m--)        {            int u,v;            scanf("%d%d",&u,&v);            addedge(u,v);            addedge(v,u);        }        for(int i=1;i<=n;i++)            if(!vis[i])                tarjan(i,-1);        for(int i=1;i<=n;i++)        {            for(int j=head[i];j!=-1;j=edge[j].next)                if(belong[i]!=belong[edge[j].to])                {                    chu[belong[i]]++;                }        }        int sum=0;        FOR(i,1,cnt){            if(chu[i]==1)                sum++;        }        printf("%d\n",(sum+1)/2);    }    return 0;}


0 0
原创粉丝点击