您的位置:首页 > 编程语言

POJ 3177 Redundant Paths (双连通)

2015-03-11 17:40 369 查看
题目地址:POJ 3177

找出各个双连通分量度数为1的点,然后作为叶子节点,那么ans=(叶子结点数+1)/2。需要注意的是有重边。

代码如下:

#include <iostream>
#include <string.h>
#include <math.h>
#include <queue>
#include <algorithm>
#include <stdlib.h>
#include <map>
#include <set>
#include <stdio.h>
using namespace std;
#define LL long long
#define pi acos(-1.0)
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
const double eqs=1e-9;
const int MAXN=5000+10;
int head[MAXN], Ecnt, deg[MAXN];
int low[MAXN], dfn[MAXN], belong[MAXN], indx, top, scc, stk[MAXN];
struct node {
int u, v, next;
} edge[21000];
void add(int u, int v)
{
edge[Ecnt].u=u;
edge[Ecnt].v=v;
edge[Ecnt].next=head[u];
head[u]=Ecnt++;
}
void tarjan(int u, int fa)
{
low[u]=dfn[u]=++indx;
stk[++top]=u;
for(int i=head[u]; i!=-1; i=edge[i].next) {
int v=edge[i].v;
if(v==fa) continue ;
if(!dfn[v]) {
tarjan(v,u);
low[u]=min(low[u],low[v]);
} else low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u]) {
scc++;
while(1) {
int v=stk[top--];
belong[v]=scc;
if(u==v) break;
}
}
}
void init()
{
memset(head,-1,sizeof(head));
memset(dfn,0,sizeof(dfn));
memset(deg,0,sizeof(deg));
Ecnt=indx=top=scc=0;
}
int main()
{
int n, m, i, j, u, v, ans, flag;
//freopen("1.txt","r",stdin);
while(scanf("%d%d",&n,&m)!=EOF) {
init();
while(m--) {
scanf("%d%d",&u,&v);
flag=0;
for(i=head[u];i!=-1;i=edge[i].next){
if(edge[i].v==v){
flag=1;
break;
}
}
if(flag) continue ;
add(u,v);
add(v,u);
}
for(i=1; i<=n; i++) {
if(!dfn[i]) tarjan(i,-1);
}
//printf("%d\n",scc);
for(i=0; i<Ecnt; i+=2) {
u=edge[i].u;
v=edge[i].v;
if(belong[u]!=belong[v]) {
deg[belong[u]]++;
deg[belong[v]]++;
}
}
ans=0;
for(i=1; i<=scc; i++) {
if(deg[i]==1)
ans++;
}
printf("%d\n",(ans+1)/2);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ACM 编程 算法 双连通