题目地址: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; }
POJ 3177 Redundant Paths (双连通)
原文地址:http://blog.csdn.net/scf0920/article/details/44201891