您的位置:首页 > 其它

Redundant Paths poj&hoj 割边 tarjan

2012-09-16 09:51 204 查看
/*题意就是至少加多少条边,使得任意两点间至少有两条不同的路。
求双连通分量。
然后统计叶子个数,即入度为1的点的个数,然后ans=(num+1)/2.
在求双连通分量的过程中low值相等的是在同一个分量里。不需要用stack来进行保存。
*/
#include <stdio.h>
#include <cstring>
#include <iostream>
using namespace std;
const int maxm=10001;
const int maxn=5001;
struct edge
{
int to,next;
} e[maxm<<1];
int n,m,cnt,t;
int head[maxn],low[maxn],dfn[maxn],in[maxn];
bool vis[maxn];
void add(int i,int j)
{
e[t].to=j;
e[t].next=head[i];
head[i]=t++;
}
void tarjan(int u,int f)
{
vis[u]=true;
low[u]=dfn[u]=++cnt;
for(int i=head[u]; i!=-1; i=e[i].next)
{
int v=e[i].to;
if(f==v) continue;
if(!vis[v]) tarjan(v,u);
low[u]=min(low[u],low[v]);
}
}
bool judge(int a,int b)
{
for(int i=head[a]; i!=-1; i=e[i].next)
if(e[i].to==b) return false;
return true;
}
int main()
{
while(scanf("%d%d",&n,&m)==2)
{
memset(head,-1,sizeof(head));
memset(e,0,sizeof(e));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(in,0,sizeof(in));
memset(vis,false,sizeof(vis));
t=cnt=0;
int u,v;
while(m--)
{
scanf("%d%d",&u,&v);
if(judge(u,v))
{
add(u,v);
add(v,u);
}
}
tarjan(1,0);
for(int i=1; i<=n; i++)
{
for(int j=head[i]; j!=-1; j=e[j].next)
{
int v=e[j].to;
if(low[i]!=low[v])
in[low[i]]++;
}
}
int ans=0;
for(int i=1; i<=n; i++)
if(in[i]==1) ans++;
printf("%d\n",(ans+1)/2);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: