【tree】codeforces 19E.Fairy
http://codeforces.com/problemset/problem/19/E
再次倒在WJMZBMR面前=。=,看了他的题解才懂这个题。。
题意很简单,给你一个图,问你有哪些边删去之后(只删除一条)图将变成2部图。。。做法是构造出一棵生成树,树必定是2部图,将所有节点染色,之后根据染色结果将剩下的所有非树边分成两个集合,集合A中边连着两个不同颜色的点,集合B中边连着两个相同颜色的点。。
先考虑非树边很容易根据集合B大小,分成等于0 , 等于1, 大于1三种情况,
再考虑树边,我们将非树边的边的两个节点在树中的路径定义为该边的路径,则如果集合B中的某一条边的路径没有经过树边e,则删去e仍然存在一奇数环;同时如果集合A中某条边的路径以及集合B中某条边的路径同时经过树边e,则删出树边e仍存在奇数环。。除了这两种情况剩下的树边都是答案了,这两种情况也可以简单画一下便明白。。最后,可以用树分治,或者树剖分来统计树上边被路径覆盖次数,复杂度O(mlogn),最后附剖分版本程序
View Code
1 //By Lin 2 #include<cstdio> 3 #include<cstring> 4 #include<vector> 5 #include<algorithm> 6 #define maxn 10010 7 using namespace std; 8 9 int n,m; 10 vector<int> ans; 11 int ecnt; 12 struct Edge{ 13 int to,num; 14 Edge *next; 15 }*mat[maxn],edges[maxn*2]; 16 void link(int x,int to,int num){ 17 edges[ecnt].to = to; 18 edges[ecnt].num= num; 19 edges[ecnt].next = mat[x]; 20 mat[x] = &edges[ecnt++]; 21 } 22 23 struct Node{ 24 int x,y,num; 25 Node(int _x,int _y,int _num):x(_x),y(_y),num(_num){} 26 }; 27 vector<Node> data; 28 int p[maxn]; 29 int Find(int x){ 30 return p[x]==x?x:(p[x]=Find(p[x])); 31 } 32 33 int size[maxn],son[maxn],top[maxn],dep[maxn],fa[maxn],cnt; 34 int id[maxn],in_tree[maxn],w[maxn],sum[2][maxn]; 35 bool col[maxn]; 36 void dfs1(int x,int father,bool cc){ 37 col[x] = cc; 38 size[x] = 1; 39 son[x] = -1; 40 for ( Edge *p = mat[x]; p ; p = p->next ){ 41 int to = p->to; 42 if ( to == father ) continue; 43 dep[to] = dep[x]+1; 44 fa[to] = x; 45 id[to] = p->num; 46 dfs1( to , x, !cc ); 47 size[x] += size[to]; 48 if ( son[x] == -1 || size[to] > size[son[x]] ) son[x] = to; 49 } 50 } 51 52 void dfs2(int x,int father,int tp){ 53 top[x] = tp; 54 w[ in_tree[x] = cnt++ ] = x; 55 if ( son[x] == -1 ) return; 56 dfs2( son[x] , x , tp ); 57 for ( Edge *p = mat[x]; p ; p = p->next ){ 58 int to = p->to; 59 if ( to == father || to == son[x] ) continue; 60 dfs2(to,x,to); 61 } 62 } 63 64 int main(){ 65 scanf("%d%d", &n, &m ); 66 for (int i = 1; i<=n; i++) p[i] = i; 67 for (int i = 0; i<m; i++) { 68 int x,y; 69 scanf("%d%d", &x, &y ); 70 if ( Find(x) == Find(y) ) data.push_back( Node(x,y,i+1) ); 71 else{ 72 p[Find(x)] = Find(y); 73 link( x , y , i+1 ) , link( y , x , i+1 ); 74 } 75 } 76 for (int i = 1; i<=n; i++) if ( p[i] == i ) link(0,i,0); 77 dfs1( 0 , -1 , 1 ); 78 dfs2( 0 , -1 , 0 ); 79 int tol = 0; 80 for (int i = 0; i<data.size(); i++) tol += col[data[i].x] == col[data[i].y]; 81 for (int i = 0; i<data.size(); i++){ 82 if ( tol == 0 || tol == 1 && col[data[i].x] == col[data[i].y] ) ans.push_back( data[i].num ); 83 int k = col[data[i].x] != col[data[i].y]; 84 int u = data[i].x , v = data[i].y; 85 while ( top[u] != top[v] ) { 86 if ( dep[top[u]] < dep[top[v]] ) swap(u,v); 87 sum[k][in_tree[u]+1]--; 88 sum[k][in_tree[top[u]]]++; 89 u = fa[top[u]]; 90 } 91 if ( dep[u] < dep[v] ) swap(u,v); 92 sum[k][in_tree[v]+1]++; 93 sum[k][in_tree[u]+1]--; 94 } 95 for (int i = 1; i<=n; i++) { 96 sum[0][i] += sum[0][i-1]; 97 sum[1][i] += sum[1][i-1]; 98 if ( (tol == 0 || sum[0][i] == tol && sum[1][i] == 0) && id[w[i]] ) ans.push_back( id[w[i]] ); 99 } 100 sort( ans.begin() , ans.end() ); 101 printf("%d\n" , (int)ans.size() ); 102 for (int i = 0; i<ans.size(); i++) printf("%d%c" , ans[i] , i == ans.size()-1?'\n':' ' ); 103 return 0; 104 }