将一棵树修改成另外一棵树最少的步数

题意:现在给出两棵树, 现在想要让这两棵树变成一模一样的树(点和边都对应一样),现在有一种操作, 可以在一棵树上添加一条边,添加一条边之后会形成一个环, 那么这时间需要从这个环中删除一条边。问至少需要多少步能达到这个目的,并输出方案。

思路: 可以说明将一棵树修改成另外一棵树,不会使最优答案变坏。 因为这个操作是可逆的。

 那么现在所要做的就是将一棵树变成另外一棵树所需要的最小步数。我先遍历第一个图, 如果第二个图中没有这个边, 那么我就要加上这个边, 但是我要删哪条边呢? 假设当前的点为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  }

 

 

posted @ 2012-10-01 17:55  Gu Feiyang  阅读(772)  评论(0)    收藏  举报