你有一张n个点的完全图(即任意两点之间都有无向边)
现在给出这张图的两棵生成树
定义一次操作为:在任意一棵生成树中删除一条边后再加入一条边(必须在同一棵树中操作),同时需要保证操作完后仍然是一棵树
问使得两棵树相同的最少操作次数,若不存在合法的操作方案,输出-1
注意:这里的相同指的是点集与边集均相同,也就是对于第一棵树中的边(u, v),第二棵树中一定存在边(u, v)或(v, u),再不懂请看样例解释。
输入描述:
一个整数n表示无向图的点数
接下来n - 1行,每行两个整数u, v表示第一棵生成树中的边
再接下来n - 1行,每行两个整数u, v表示第二棵生成树中的边
输出描述:
一个整数,表示最少操作次数
思路:
刚看到这个题的时候,花了一个图,然后想到找不同的边数
都是n - 1条边,假设有x条不同的边,说明这x条边都要删了然后加上x条边
反过来,n - 1 - 相同的边数也是本题答案
大佬的代码,太棒了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<algorithm> #include<set> using namespace std; struct node { int x, y; bool operator<(const node& a) const {//不是内置类型,需要重载 if (x != a.x) return x < a.x; else return y < a.y; } }; int main() { set<node> v; int n; cin >> n; int xx,yy; for (int i = 0; i < n - 1; i++) { cin >> xx >> yy; if (xx > yy) swap(xx, yy); v.insert(node{xx,yy}); } /*for (auto i : v) {//可以输出观察一下 cout << i.x << " "<<i.y<< endl; } */ int ans = v.size(); for (int i = 0; i < n - 1; i++) { cin >> xx >> yy; if (xx > yy) swap(xx, yy); v.insert(node{xx,yy}); } cout << v.size() - ans << endl; /*for (auto i : v) {//可以输出观察一下 cout << i.x << " "<<i.y<< endl; } */ }