Description
Input
Output
Sample Input
7 7 1 2 2 3 3 4 2 5 4 5 5 6 5 7
Sample Output
2
Hint
1 2 3Building new paths from 1 to 6 and from 4 to 7 satisfies the conditions.
+---+---+
| |
| |
6 +---+---+ 4
/ 5
/
/
7 +
1 2 3Check some of the routes:
+---+---+
: | |
: | |
6 +---+---+ 4
/ 5 :
/ :
/ :
7 + - - - -
题目大意:
解题思路:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<stack>
using namespace std;
const int maxn = 5100;
struct Edge{
int from,to,dist,next;
Edge(){}
Edge(int _to,int _next):to(_to),next(_next){}
}edges[maxn*4]; //无向图的边
int head[maxn], tot; //邻接表
int dfs_clock, dfn[maxn]; //时间戳
//Stack:存放边双连通节点、instack:在栈中、ebccno:节点所在分量编号、ebcc_cnt分量数目(从1开始编号)
int Stack[maxn], instack[maxn], top, ebccno[maxn], ebcc_cnt;
int deg[maxn];//记录缩点的度
void init(){
tot = 0;
dfs_clock = 0;
top = 0;
ebcc_cnt = 0;
memset(deg,0,sizeof(deg));
memset(head,-1,sizeof(head));
}
void AddEdge(int _u,int _v){
edges[tot] = Edge(_v,head[_u]);
head[_u] = tot++;
}
int dfs(int u,int fa){ //这里的fa是记录的边的编号,用来处理重边
int lowu = dfn[u] = ++dfs_clock;
Stack[++top] = u; //将每个访问的结点放入栈中
// instack[u] = 1;
for(int i = head[u]; i != -1; i = edges[i].next){
int v = edges[i].to;
if(!dfn[v]){ //如果v没有访问过
int lowv = dfs(v,i); //v及v的后代能访问到的最远祖先
lowu = min(lowu,lowv); //用后代来更新lowu
//如果v已经在栈中了,并且这条边不是回边(一条无向边,拆成了有向边,回指了父亲的这条有向边)
}else if(dfn[v] < dfn[u] && (fa^1) != i){ //有人在这里用instack[v]替代了判断已经在栈中
lowu = min(lowu,dfn[v]); //用反向边更新lowu
}
}
if(dfn[u] == lowu){ //找到一个边双连通分量
ebcc_cnt++;
for(;;){
int v = Stack[top--];
// instack[v] = 0;
ebccno[v] = ebcc_cnt; //把节点划分到分量中
if(u == v){
break;
}
}
}
// low[u] = lowu;
return lowu;
}
void find_ebcc(int n){
memset(dfn,0,sizeof(dfn));
memset(instack,0,sizeof(instack));
for(int i = 1; i <= n; i++){
if(!dfn[i]){
dfs(i,-1);
}
}
}
int main(){
int n,m;
while(scanf("%d%d",&n,&m)!=EOF){
init();
int a,b;
for(int i = 0; i < m; i++){
scanf("%d%d",&a,&b);
AddEdge(a,b);
AddEdge(b,a);
}
find_ebcc(n);
for(int i = 1; i <= n; i++){
for(int j = head[i]; j != -1; j = edges[j].next){
int v = edges[j].to;
if(ebccno[i] != ebccno[v]){
deg[ebccno[v]]++;
}
}
}
int leaf = 0;
for(int i = 1; i <= ebcc_cnt; i++){
if(deg[i] == 1){
leaf++;
}
}
printf("%d\n",(leaf+1)/2);
}
return 0;
}
POJ 3177——Redundant Paths——————【加边形成边双连通图】
原文:http://www.cnblogs.com/chengsheng/p/4940944.html