HDU 3394 Railway 点双连通分量

来源:互联网 发布:知乎 武侠 编辑:程序博客网 时间:2024/06/04 18:39

题意

给定一个无向图,找出不在任意一个环上的边数和同时在多个环上的边数。

思路

点-双连通分量如果在边数等于点数,那么形成一个环,边数多于点数,说明环中有多条边。

#include<cstdio>#include<iostream>#include<algorithm>#include<cstring>#include<vector>#include<string>#include<queue>#include<stack>#include<set>#include<map>#define ll long longusing namespace std;const int INF = ( 2e9 ) + 2;const ll maxn = 10010;struct edge{    int u,v;};stack<edge> st;vector<int> g[maxn],blocks[maxn];int dfn[maxn],low[maxn];bool vis[maxn];int index,bcc;int ans1,ans2;void init(int n){    for(int i=0;i<=n;i++)    g[i].clear(),blocks[i].clear();    memset(dfn,0,sizeof(dfn));    while(!st.empty())st.pop();    bcc=ans1=ans2=0;}void tarjan(int u,int fa){    dfn[u]=low[u]=++index;    int len=g[u].size();    for(int i=0;i<len;i++)    {        int v=g[u][i];        if(v==fa)continue;//无重边        if(!dfn[v])        {            st.push(edge{u,v});            tarjan(v,u);            low[u]=min(low[u],low[v]);            if(low[v]>=dfn[u])            {                bcc++;                memset(vis,0,sizeof(vis));                int cnt1,cnt2;                cnt1=cnt2=0;                while(!st.empty())                {                    edge temp=st.top();st.pop();                    int x=temp.u,y=temp.v;                    cnt2++;                    if(!vis[x])blocks[bcc].push_back(x),vis[x]=1,cnt1++;                    if(!vis[y])blocks[bcc].push_back(y),vis[y]=1,cnt1++;                    if(x==u&&y==v)break;                }                if(cnt2>cnt1)ans2+=cnt2;            }            if(low[v]>dfn[u])ans1++;        }        else if(dfn[v]<dfn[u])        {            st.push(edge{u,v});            low[u]=min(low[u],dfn[v]);        }    }}void outputblocks(){    printf("blocks:\n");    for(int i=1;i<=bcc;i++)    {        printf("%d: ",i);        for(int j=0;j<blocks[i].size();j++)        printf("%d ",blocks[i][j]);        puts("");    }}int main(){    int n,m,u,v;    while(~scanf("%d%d",&n,&m)&&(n+m))    {        init(n);        for(int i=0;i<m;i++)        {            scanf("%d%d",&u,&v);            g[u].push_back(v);            g[v].push_back(u);        }        for(int i=0;i<n;i++)        if(!dfn[i])        tarjan(i,-1);        printf("%d %d\n",ans1,ans2);    }}
原创粉丝点击