题目:
http://acm.hdu.edu.cn/showproblem.php?pid=3394题意:
有许多铁路,他们形成了许多环,现在要找出他们中不存在任何一个环中的铁路数和同时存在于多个环中的铁路数。思路:
不存在于任何一个环中也就是无向图中的桥,所以这道题是求无向图的双连通分量,找出所有的桥就是第一个答案,存在与多个环中就是某个双联通分量相同中的边数大于点数,那么这个双联通分量就不只是一个环了,形成多个环,所有的点也就在这些环中,也就是该双连通分量中的所有点都同时存在与多个环中,也就是求出所有的双连通分量然后判断。
注意要形成环是求点的双连通分量,这样才满足只有一个环的双连通分量中的边数等于点数。
具体双联通分量的求法看这里:http://blog.csdn.net/kopyh/article/details/48321131
代码:
#define N 11234
int n,m;
int flag,sum,res,ans,len,ans1,ans2;
int a[N],b[N];
struct node
{
int x,y;
node(int a=0,int b=0)
{
x=a;y=b;
}
}tn;
vector<int>g[N];
stack<node>st;
int dfn[N],low[N];
int inStack[N],belong[N];
int index;
void init()
{
for(int i=0;i<N;i++)
g[i].clear();
while(!st.empty())st.pop();
memset(dfn, 0, sizeof(dfn));
memset(low, 0, sizeof(low));
ans1=ans2=0;
index = 1;
}
void judge(int u,int v)
{
int x,y;
res=0;ans=0;
memset(b,0,sizeof(b));
while(!st.empty())
{
tn = st.top();
st.pop();
x=tn.x;y=tn.y;
ans++;
if(!b[y])res++,b[y]=1;
if(x==u)
break;
if(!b[x])res++,b[x]=1;
}
if(ans>res)ans2+=ans;
}
void tarjan(int x,int fa)
{
low[x] = dfn[x] = index++;
int len = g[x].size();
for(int i=0;i<len;i++)
{
int t=g[x][i];
if(t==fa)
continue;
if(!dfn[t] && dfn[t]<dfn[x])
{
st.push(node(x,t));
tarjan(t,x);
low[x] = min(low[x], low[t]);
if(dfn[x]<=low[t])
{
if(dfn[x]<low[t])
ans1++;
judge(x,t);
}
}
else if(dfn[t] < dfn[x])
{
st.push(node(x,t));
low[x] = min(low[x], dfn[t]);
}
}
}
void solve()
{
for(int i = 1; i <= n; i++)
if(!dfn[i])
tarjan(i,i);
}
int main()
{
int i,j,k,kk,t,x,y,z;
while(scanf("%d%d",&n,&m)!=EOF&&n)
{
init();
for(i=0;i<m;i++)
{
scanf("%d%d",&x,&y);
x++;y++;
g[x].push_back(y);
g[y].push_back(x);
}
solve();
printf("%d %d\n",ans1,ans2);
}
return 0;
}