有一天,天才錢
和學霸周
閒的無聊玩起了遊戲,遊戲內容是這樣的,現在有nn個城堡
mm個不同的橋,每乙個橋連線著兩個不同的城堡,並且已知這mm個橋可以使nn個城堡連通,此外每乙個橋都有重量vv。兩位大爺需要給出選擇橋的方案使得所有城堡被連通,注意兩位大爺的方案不能完全相同(至少存在乙個橋不相同),已知周大爺
優先給出方案(因此錢大爺
的方案必須不同於周大爺
)。規則很詭異,如果錢大爺
的方案中橋的重量之和≤≤周大爺
的方案中橋的重量之和,那麼錢大爺
獲勝,反之周大爺
獲勝。兩位大爺都很聰明,他們會給出最優方案。現在你需要計算誰會贏。
input
第一行輸入兩個值n(2≤n≤2000),m (n≤m≤200000)
接下來m行,每一行輸入三個值a (1≤a≤n),b(1≤b≤n),v(1≤v≤1018),其中a!=b
output
如果錢大爺
獲勝輸出「zin
」,反之輸出「ogisosetsuna
」 。
sample input
2 2
1 2 1
1 2 1
sample output
zin
題意就是判斷最小生成樹是否唯一。
判斷最小生成樹是否唯一(求次小生成樹)的思路:
方法一:先跑一趟最小生成樹,記錄下來對應的邊,由於次小生成樹至少有一條邊不同於最小生成樹,所以我們可以列舉最小生成樹的每一條邊不在次小生成樹中,然後跑一趟
kursal
演算法,看是否次小生成樹的權值是否等於最小生成樹,不過複雜度有點大是o
(m*n+mlogm
)其中n
表示列舉次數,
m表示邊數 (
本題會tle)
就是刪除最小生成樹的一條邊,再求次小生成樹看權值是否與最小生成樹相同;
方法二:先證明乙個結論,次小生成樹一定可以由最小生成樹刪除乙個邊再添上乙個邊得到。在證明中,我們可以得知當我們新增新邊後需要刪除新構成的環上的一條邊,我們顯然要刪除 除了新邊外 權值最大的那個邊,這個我們可以o(
n^2)先把最小生成樹的所有路徑中邊權值最大的處理出來(
dfs即可),此後我們只用列舉每一條新加入的邊,然後o(
1)的獲得替換邊,所以尋找的複雜度是 o(
m+ n^2
) 總體的複雜度為o(
mlogm+m
+ n^2
) ,當然我們不用擔心資料範圍,因為只用看,替換邊的權值是否等於新加入邊的權值。 (沒懂t__t)
似乎是求出最小生成樹之後,再加入一條邊,這時肯定構成環了,所以就要刪除除新加邊之外權值最大的那條邊。
好像明白了,那麼就來做乙個轉換,列舉每一條邊,只需要列舉權值相同的邊就行啦,因為權值不同,一定無法使次小生成樹和最小生成樹權值相同;
那麼現在考慮是否只要只要有權值相同的邊,是否最小生成樹就不唯一呢?很顯然不是的,以為假設權值相同的邊無限大,生成過程肯定不需要這樣的邊,自然可以想到要是用於生成最小生成樹的邊有權值一樣的,那麼最小生成樹就不唯一。
#include#include#include#include#includeusing namespace std;
const int maxn=2e3+5;
int pre[10005];
int m;
int n;
int tot;
int find(int x)
int i=x;
int farther;
while(pre[i]!=i)
return root;
}bool join(int a,int b)
return false;
}struct path
a[200005];
bool cmp (path t1,path t2)
int main()
最小生成樹 次小生成樹
一 最小生成樹 說到生成樹首先要解釋一下樹,樹是乙個聯通的無向無環圖,多棵樹的集合則被稱為森林。因此,樹具有許多性質 1.兩點之間的路徑是唯一的。2.邊數等於點數減一。3.連線任意兩點都會生成乙個環。對於乙個無向聯通圖g的子圖,如果它包含g的所有點,則它被稱為g的生成樹,而各邊權和最小的生成樹則被稱...
次小生成樹
演算法引入 設g v,e,w 是連通的無向圖,t是圖g的一棵最小生成樹 如果有另一棵樹t1,滿足不存在樹t t t1 則稱t1是圖g的次小生成樹 演算法思想 鄰集的概念 由t進行一次可行交換得到的新的生成樹所組成的集合,稱為樹t的鄰集,記為n t 設t是圖g的最小生成樹,如果t1滿足 t1 min,...
次小生成樹
分類 圖論 2013 02 12 15 03 32人閱讀收藏 舉報次小生成樹 在求最小生成樹時,用陣列path i j 來表示mst中i到j最大邊權。求完後,直接列舉所有不在mst中的邊,把它加入到mst中構成一棵新的樹,且該樹有環,此環是由剛加入的邊 i,j 造成的,所以可以通過刪除path i ...