POJ3177 分离的路径
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ3177 分离的路径相关的知识,希望对你有一定的参考价值。
题目大意:
有 F个牧场,现在一个牧群经常需要从一个牧场迁移到另一个牧场。奶牛们已经厌烦老 是走同一条路,
所以有必要再新修几条路,这样它们从一个牧场迁移到另一个牧场时总是可 以选择至少两条独立的路。现在 F 个
牧场的任何两个牧场之间已经至少有一条路了,奶牛们需要至少有两条。 给定现有的 R 条直接连接两个牧场的路,
计算至少需要新修多少条直接连接两个牧场的路,使得任何两个牧场之间至少有两条独立的路。两条独立的路是指
没有公共边的路,但可以经过同一个中间顶点。
1<=F<=5000 ; F-1<=R<=10000
输入格式:
第一行两个数F,R
接下去R行,每行两个数a,b表示a与b有一条道路
输出格式:
至少要加入的边的数量
输入样例:
7 7 1 2 2 3 3 4 2 5 4 5 5 6 5 7
输出样例:
2
题解:
把一张有桥的无向图加边变成边双联通图,先求出所有的桥,把非桥的双联通图缩点,可以用并查集维护,然
后对于每个桥两端的代表点的度数加1。
度数为1的就是缩点后的叶节点,对于每对叶节点可以用一条边使之产生环而变为双联通图,答案即为(num+1)/2。(num为叶节点的数量)
1 #include<iostream> 2 #include<cstdlib> 3 #include<cstdio> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 struct node 8 { 9 int next,to,fr; 10 } e[20005]; 11 int cnt=1,head[5005],time,from[5005],fa[5005],in[5005]; 12 int dfn[5005],low[5005]; 13 bool cut[20005]; 14 inline void insert(int u,int v) 15 { 16 e[++cnt].next=head[u]; 17 head[u]=cnt; 18 e[cnt].to=v; 19 e[cnt].fr=u; 20 } 21 inline int find(int x) 22 { 23 return x==fa[x]?x:fa[x]=find(fa[x]); 24 } 25 inline void tarjan(int now) 26 { 27 dfn[now]=low[now]=++time; 28 for(int i=head[now];i;i=e[i].next) 29 { 30 if(i==(from[now]^1)) continue; 31 if(!dfn[e[i].to]) 32 { 33 from[e[i].to]=i; 34 tarjan(e[i].to); 35 low[now]=min(low[now],low[e[i].to]); 36 if(low[e[i].to]>dfn[now]) 37 cut[i]=cut[i^1]=1; 38 } 39 else low[now]=min(low[now],dfn[e[i].to]); 40 } 41 } 42 int main() 43 { 44 int n,m,u,v,num=0; 45 scanf("%d%d",&n,&m); 46 for(int i=1;i<=m;i++) 47 { 48 scanf("%d%d",&u,&v); 49 insert(u,v); 50 insert(v,u); 51 } 52 tarjan(1); 53 for(int i=1;i<=n;i++) fa[i]=i; 54 for(int i=2;i<=cnt;i+=2) 55 if(!cut[i]) fa[find(e[i].fr)]=find(e[i].to); 56 for(int i=2;i<=cnt;i+=2) 57 if(cut[i]) in[find(e[i].fr)]++,in[find(e[i].to)]++; 58 for(int i=1;i<=n;i++) 59 if(find(i)==i && in[i]==1) num++; 60 printf("%d",(num+1)/2); 61 }
以上是关于POJ3177 分离的路径的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ1718&&POJ3177Redundant Paths
POJ 3177 - Redundant Paths - 双连通分量