当前位置: 代码迷 >> 综合 >> poj3177 - Redundant Paths-tarjan缩点+求度为1的点
  详细解决方案

poj3177 - Redundant Paths-tarjan缩点+求度为1的点

热度:56   发布时间:2023-12-19 10:43:38.0

把无向图的边双联通块缩成一个点,然后建立一棵树。

假如树中度数为1的点的个数为x个。

那么结果为(x+1)/2.

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
#define maxn 5500
#define maxm 22000
#define mem(a,b) (memset(a,b,sizeof(a)))
struct gra
{int n,m;struct list{int u,v,next;}edge[maxm];int head[maxn],num,vis[maxm];int dnf[maxn],low[maxn],times;int cnt[maxn];void init(int x,int y){num=0;times=1;n=x;m=y;mem(head,-1);mem(dnf,0);mem(low,0);mem(vis,0);mem(cnt,0);}void add(int u,int v){edge[num].u=u;edge[num].v=v;edge[num].next=head[u];head[u]=num++;}void tarjan(int x){dnf[x]=low[x]=times++;for(int i=head[x];i!=-1;i=edge[i].next){int y=edge[i].v;if(vis[i])continue;vis[i]=vis[i^1]=1;if(!dnf[y]){tarjan(y);low[x]=min(low[x],low[y]);}else{low[x]=min(low[x],dnf[y]);}}}void start(){tarjan(1);for(int x=1;x<=n;x++){for(int i=head[x];i!=-1;i=edge[i].next){int y=edge[i].v;if(low[x]!=low[y]){cnt[low[y]]++;}}}int ans=0;for(int i=1;i<=n;i++){if(cnt[i]==1)ans++;}cout<<(ans+1)/2<<endl;}
}G;
int main()
{int n,m,i,a,b;while(~scanf("%d%d",&n,&m)){G.init(n,m);for(i=1;i<=m;i++){scanf("%d%d",&a,&b);G.add(a,b);G.add(b,a);}G.start();}return 0;
}


  相关解决方案