题意:一张无向图中告诉你一个dfs树,还有若干反向边。问你如何选取最小的边使得所有只包含一条反向边的环被覆盖。
思路:我们把有反向边的点与反向边连接的点在树上的路径称作一个区间,可以想到了从叶子结点开始向上到一个区间到不得不选边覆盖的时候在选边,同样能选的边越靠近根节点越好。关键是在程序实现上,自己实现的时候用的是vector<bool>来标记边的状态果断超时,网上搜到一种用bitset,以前从来没用过太神了,代码又短思路又清晰参考http://hi.baidu.com/zjut_dd/item/5d3543e55ba0ebebe0a5d4d7
主要就是从低至上每次遇到反向边则记录,若是当前节点到其父亲结点必须选了则选上(选上了则代表当前子树的所有结点连接的反向边全部搞定了),否则的话则向上一层传递还未选择的区间。
代码如下:
1 /************************************************** 2 * Author : xiaohao Z 3 * Blog : http://www.cnblogs.com/shu-xiaohao/ 4 * Last modified : 2014-05-13 22:22 5 * Filename : hdu_4582.cpp 6 * Description : 7 * ************************************************/ 8 9 #include <iostream> 10 #include <cstdio> 11 #include <cstring> 12 #include <cstdlib> 13 #include <cmath> 14 #include <algorithm> 15 #include <queue> 16 #include <stack> 17 #include <vector> 18 #include <set> 19 #include <map> 20 #define MP(a, b) make_pair(a, b) 21 #define PB(a) push_back(a) 22 23 using namespace std; 24 typedef long long ll; 25 typedef pair<int, int> pii; 26 typedef pair<unsigned int,unsigned int> puu; 27 typedef pair<int, double> pid; 28 typedef pair<ll, int> pli; 29 typedef pair<int, ll> pil; 30 31 const int INF = 0x3f3f3f3f; 32 const double eps = 1E-6; 33 const int LEN = 2010; 34 vector<int> Map1[LEN], Map2[LEN]; 35 int vex[LEN][1010]; 36 int n, m, vis[LEN], ans; 37 38 void setvex(int pa, int pb){ 39 int tn = pb/30; 40 vex[pa][tn] |= (1<<(pb%30)); 41 } 42 43 bool getvex(int pa, int pb){ 44 int tn = pb/30; 45 if(vex[pa][tn] & (1<<(pb%30))) return true; 46 return false; 47 } 48 49 void dfs(int v, int fa){ 50 vis[v] = 1; 51 memset(vex[v], 0, sizeof vex[v]); 52 for(int i=0; i<Map2[v].size(); i++){ 53 int x = Map2[v][i]; 54 if(vis[x]) setvex(v, x); 55 } 56 for(int i=0; i<Map1[v].size(); i++){ 57 int x = Map1[v][i]; 58 if(x != fa) dfs(x, v); 59 } 60 if(fa != -1 && getvex(v, fa)) ans++; 61 else if(fa != -1){ 62 for(int i=0; i<210; i++) vex[fa][i] |= vex[v][i]; 63 } 64 } 65 66 int main() 67 { 68 // freopen("in.txt", "r", stdin); 69 70 int a, b; 71 while(scanf("%d%d", &n, &m)!=EOF){ 72 if(!n && !m) break; 73 ans = 0; 74 for(int i=0; i<LEN; i++) Map1[i].clear(); 75 for(int i=0; i<LEN; i++) Map2[i].clear(); 76 for(int i=0; i<m; i++){ 77 scanf("%d%d", &a, &b); 78 if(i < n-1){ 79 Map1[a].PB(b); 80 Map1[b].PB(a); 81 }else{ 82 Map2[a].PB(b); 83 Map2[b].PB(a); 84 } 85 } 86 memset(vis, 0, sizeof vis); 87 dfs(1, -1); 88 printf("%d ", ans); 89 } 90 return 0; 91 }