思维题
刚刚开始拿到这个题目的时候感觉应该会很麻烦,并且一开始的思路就是错的,想到了去建一个最小生成树,那么后序该怎么比较呢,就感觉很烦,后序看了大佬的题解,原来这是一个思维题,首先我们对n-1条边进行赋值操作就让它指向一个对应的值,然后在对后序n-1条边进行判断,题目根本不需要我们建图只需要我们去判断相差几条边,因为边的总数是不变的,所以就是说你每增加一条边就会相应的减少一条边,这是人为的去想的,但是代码只需要求出一共需要修改几条边,所以我们就对剩下的边进行操作,如果给出的这两个点之间没有边,那么说明就要在这个两个点之间连一条边,同时对应的减去一条边,ans是修改的次数,每修改一次就加一个这就是最终的答案
方法一:正方向求解
正反向求解是求一共需要修改多少条边,也就是一共有多少条边不同
#include <bits/stdc++.h> using namespace std; const int maxn = 1e5 + 10; int a[maxn]; int main() { int n, u, v, ans; while (~scanf("%d", &n)) { ans = 0; for (int i = 1; i <= n - 1; ++i) { scanf("%d%d", &u, &v); a[u] = v;//进行赋值操作 } for (int i = 1; i <= n - 1; ++i) { scanf("%d%d", &u, &v); if (a[u] != v && a[v] != u)//如果这两个点之间没有边 ++ans; } printf("%d\n", ans); } }
方法二:反方向求解
反方向求解就是求出一共有多少条边相同,然后就用总数减去相同的数量就是需要修改的数量
#include <bits/stdc++.h> using namespace std; const int maxn = 1e5 + 10; int a[maxn]; int main() { int n, u, v, ans; while (~scanf("%d", &n)) { ans = 0; for (int i = 1; i <= n - 1; ++i) { scanf("%d%d", &u, &v); a[u] = v; } for (int i = 1; i <= n - 1; ++i) { scanf("%d%d", &u, &v); if (a[u] == v || a[v] == u) ++ans; } printf("%d\n", n - 1 - ans); } }