将一棵树修改成另外一棵树最少的步数
题意:现在给出两棵树, 现在想要让这两棵树变成一模一样的树(点和边都对应一样),现在有一种操作, 可以在一棵树上添加一条边,添加一条边之后会形成一个环, 那么这时间需要从这个环中删除一条边。问至少需要多少步能达到这个目的,并输出方案。
思路: 可以说明将一棵树修改成另外一棵树,不会使最优答案变坏。 因为这个操作是可逆的。
那么现在所要做的就是将一棵树变成另外一棵树所需要的最小步数。我先遍历第一个图, 如果第二个图中没有这个边, 那么我就要加上这个边, 但是我要删哪条边呢? 假设当前的点为u,v,因为在第二图中中因为没有u<--->v, 我在第二个图中搜从u到v的路径, 从u到v的路径上首先出现的边如果图1中没有那么就把这个边删掉。 这样最后就能算出结果。
下面说明这样做的正确性, 加上的那条边是肯定需要加上的, 同时去掉了一个不影响答案的边,这样就能保证最后加上的边是最少的。
AC代码:
View Code
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <string> 5 #include <queue> 6 #include <algorithm> 7 #include <vector> 8 #include <set> 9 using namespace std; 10 typedef long long LL; 11 const int N = 2005; 12 set<int>g1[N],g2[N]; 13 14 struct EDGE 15 { 16 int x1, y1, x2, y2; 17 }p[N]; 18 19 int n, ans, path[N], step; 20 21 void init() 22 { 23 int u, v; 24 scanf("%d", &n); 25 for(int i=1; i<n; i++) 26 { 27 scanf("%d%d", &u, &v); 28 g1[u].insert(v); 29 g1[v].insert(u); 30 } 31 32 for(int i=1; i<n; i++) 33 { 34 scanf("%d%d", &u, &v); 35 g2[u].insert(v); 36 g2[v].insert(u); 37 } 38 } 39 40 bool dfs1(int u, int pre, int goal) 41 { 42 if(u == goal) return true; 43 int v; 44 set<int>::iterator it; 45 for(it=g2[u].begin(); it!=g2[u].end(); it++) 46 { 47 v = *it; 48 if(v == pre) continue; 49 if(dfs1(v, u, goal)) 50 { 51 path[++step] = v; 52 return true; 53 } 54 } 55 return false; 56 } 57 58 void dfs(int u, int pre) 59 { 60 int v, uu, vv; 61 set<int>::iterator it, ij; 62 for(it=g1[u].begin(); it!=g1[u].end(); it++) 63 { 64 v = *it; 65 if(v == pre) continue; 66 if(g2[u].find(v) == g2[u].end()) 67 { 68 step = 0; 69 dfs1(u, -1, v); 70 uu = u; 71 for(int j=step; j>0; j--) 72 { 73 vv = path[j]; 74 if(g1[uu].find(vv) == g1[uu].end()) 75 { 76 ans++; 77 p[ans].x2 = uu; 78 p[ans].y2 = vv; 79 ij = g2[uu].find(vv); 80 g2[uu].erase(ij); 81 ij = g2[vv].find(uu); 82 g2[vv].erase(ij); 83 break; 84 } 85 uu = vv; 86 } 87 p[ans].x1 = u; 88 p[ans].y1 = v; 89 g2[u].insert(v); 90 g2[v].insert(u); 91 } 92 dfs(v, u); 93 } 94 } 95 96 void solve() 97 { 98 ans = 0; 99 dfs(1, -1); 100 printf("%d\n", ans); 101 for(int i=1; i<=ans; i++) 102 { 103 printf("2 %d %d %d %d\n",p[i].x1, p[i].y1, p[i].x2, p[i].y2); 104 } 105 } 106 107 int main() 108 { 109 init(); 110 solve(); 111 return 0; 112 }


浙公网安备 33010602011771号