标签:信息 microsoft 最好 void scan 个数 条件 sizeof class
题目描述
输入
输出
样例输入
4 4
1 2
2 3
3 2
4 3
样例输出
2
题解
DFS树
简单分析一下题目可知题目要求多少条边在简单奇环上的边的交集上,且不再简单偶环上。
判断简单环的最好方法是DFS树,所以我们可以先把整张无向图DFS一遍,然后分为树边和返祖边讨论。
对于一条返祖边,如果它连接的两个点的深度差为偶数,说明它在奇环上;否则在偶环上。并且它覆盖的边所在的奇环数或偶环数+1.
我们可以差分一下,在两个点上边打上标记,然后再遍历一遍求出每条树边在多少个奇环上,在多少个偶环上。如果满足条件则将答案+1.
注意:如果只有一条返祖边在奇环上,则将答案+1,否则对答案都没有贡献。
#include <cstdio> #include <cstring> #include <algorithm> #define N 100010 using namespace std; int head[N] , to[N << 2] , flag[N << 2] , next[N << 2] , s1[N] , s2[N] , t1[N] , t2[N] , cnt = 1 , deep[N] , num , ans; void add(int x , int y) { to[++cnt] = y , next[cnt] = head[x] , head[x] = cnt; } void dfs(int x) { int i; for(i = head[x] ; i ; i = next[i]) if(deep[to[i]] == -1) deep[to[i]] = deep[x] + 1 , flag[i] = flag[i ^ 1] = 1 , dfs(to[i]); } void query(int x) { int i; for(i = head[x] ; i ; i = next[i]) if(flag[i] && deep[to[i]] > deep[x]) query(to[i]) , s1[x] += s1[to[i]] , s2[x] += s2[to[i]]; if(deep[x] && s1[x] == num && !s2[x]) ans ++ ; } int main() { int n , m , i , x , y; scanf("%d%d" , &n , &m); for(i = 1 ; i <= m ; i ++ ) scanf("%d%d" , &x , &y) , add(x , y) , add(y , x); memset(deep , -1 , sizeof(deep)); for(i = 1 ; i <= n ; i ++ ) if(deep[i] == -1) deep[i] = 0 , dfs(i); for(x = 1 ; x <= n ; x ++ ) { for(i = head[x] ; i ; i = next[i]) { if(!flag[i] && deep[to[i]] < deep[x]) { if((deep[x] - deep[to[i]]) & 1) s2[x] ++ , s2[to[i]] -- ; else num ++ , s1[x] ++ , s1[to[i]] -- ; } } } if(num == 1) ans ++ ; for(i = 1 ; i <= n ; i ++ ) if(!deep[i]) query(i); printf("%d\n" , ans); return 0; }
标签:信息 microsoft 最好 void scan 个数 条件 sizeof class
原文地址:http://www.cnblogs.com/GXZlegend/p/7123480.html