生成树(光棍 牛客, 思维)
鏈接:https://ac.nowcoder.com/acm/contest/223/A
來源:牛客網
?
題目描述
你有一張n個點的完全圖(即任意兩點之間都有無向邊)
現在給出這張圖的兩棵生成樹
定義一次操作為:在任意一棵生成樹中刪除一條邊后再加入一條邊(必須在同一棵樹中操作),同時需要保證操作完后仍然是一棵樹
問使得兩棵樹相同的最少操作次數,若不存在合法的操作方案,輸出-1
?
注意:這里的相同指的是點集與邊集均相同,也就是對于第一棵樹中的邊(u, v),第二棵樹中一定存在邊(u, v)或(v, u),再不懂請看樣例解釋。
?
輸入描述:
一個整數n表示無向圖的點數 接下來n - 1行,每行兩個整數u, v表示第一棵生成樹中的邊 再接下來n - 1行,每行兩個整數u, v表示第二棵生成樹中的邊輸出描述:
一個整數,表示最少操作次數示例1
輸入
復制
6 6 1 1 2 2 3 3 5 5 4 1 2 2 4 4 5 5 3 6 4輸出
復制
2說明
題目中的樹如下所示
一種方案如下:
第二棵樹中刪除(2, 4),增加(2,3)
第二棵樹中刪除(4, 6),增加(1, 6)
注意:如果僅在第二棵樹中刪除(2, 4),增加(1, 6),得到的樹雖然形態相同,但是邊集不同,我們不認為它們是相同的!
?
示例2
輸入
復制
3 1 2 2 3 1 3 3 2輸出
復制
1示例3
輸入
復制
2 1 2 2 1輸出
復制
0備注:
保證輸入數據合法
?
?
思維題:剛開始沒有想到,想到好幾種辦法,但到最后都被自己推翻了。
二維數組太大,所以降成了一維數組,但卻有個問題,用一維數組存邊時,會出現重復問題,導致邊被覆蓋,那么,又該如何解決這一問題呢???
對于一顆生成樹來說,一個點最多才能夠連接兩條邊因此可以將一條邊正著存,一條邊反著存。
例如:1 ? ? ? 2
? ? ? ? ?? 1 ? ? ? 3
? ? ? ? 就可以這樣存:dp[1] = 2; dp[3] = 1;
問題就會迎刃而解:
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<string>using namespace std;const int maxn = 1e5+5; int t1[maxn];int main() {int n;scanf("%d", &n);memset(t1, 0, sizeof(t1));for(int i = 0; i < n-1; i++){int a, b;scanf("%d%d", &a, &b);if(!t1[a]) t1[a] = b;else t1[b] = a;}int cnt = 0;for(int i = 0; i < n-1; i++){int a, b;scanf("%d%d", &a, &b);if(t1[a] == b||t1[b] == a) cnt++;}printf("%d\n", n-1-cnt);return 0; }?
總結
以上是生活随笔為你收集整理的生成树(光棍 牛客, 思维)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: yxy和志愿者小姐姐番外篇之大宝宝123
- 下一篇: Cities (思维 树)