一道有很多種解法的題目
通過劃歸,發現就是求最小環
那麼立即能想到的演算法:1、tarjan求強連通分量,最無腦
2、對於每個連通分量用topo sort,相當於剪去其他不在環上的邊
不過用帶權並查集也可以解決這道題目
首先發現只要一條邊連線的兩個點a、b在之前已經在乙個集合中,則必定會形成乙個環
那麼難點就在於如何每次高效地求出環的大小
確實可以維護每個點到其根節點的距離,但每次merge操作要改變很多點的值
於是我們可以每次merge時只維護其到父節點的距離,不用有其他操作
而在find時再通過遞迴求出這個點到根節點的距離
ex:有3個點a、b、c,f[a]=b,f[b]=c。在find前d[a]=cost(a,b),d[b]=cost(b,c),在遞迴時僅要d[a]+=d[f[a]]即可。
可以發現這樣的處理和線段樹中的lazy_tag運用了同樣的思想
為了降低複雜度(只要不影響其他值的查詢)在修改操作時不用對可能受影響的點全部進行修改,只維護最近點的資料,在查詢操作時統一操作即可
tips:1、在這樣進行維護時,合併操作不能使用啟發式合併,因為在查詢時必須保證一條邊兩個節點間的父子關係不發生改變
2、n個點n-1條邊絕不意味著只可能出現乙個環,很可能有多個連通分量,從而出現多個環
1 #include 23using
namespace
std;
4int n,f[200005],d[200005];5
6int find(intx)7
14else
return
x;15}16
17int
main()
1831 cout <3233
return0;
34 }
NOIP 2015 D1 T2 資訊傳遞
問題描述 有n個同學 編號為1到n 正在玩乙個資訊傳遞的遊戲。在遊戲裡每人都有乙個固定的資訊傳遞物件,其中,編號為i的同學的資訊傳遞物件是編號為ti同學。遊戲開始時,每人都只知道自己的生日。之後每一輪中,所有人會同時將自己當前所知的生日資訊告訴各自的資訊傳遞物件 注意 可能有人可以從若干人那裡獲取資...
noip2015 d1t2 資訊傳遞
題目鏈結 題意 給定乙個圖,每個節點的出度為1,求最小環的結點數 參考 可以先把不在環內的點清除掉,再對於每個環跑一遍長度 1 include2 include3 include4 using namespace std 5 define maxn 200010 6int in degree max...
noip2015day1t2 資訊傳遞
把每個同學看成乙個點,傳遞關係看成一條邊,點數等於邊數,因此圖由若干個環或環鏈復合邊數等於點數的東西組成,不存在孤立鏈。在圖上,傳遞一輪後,每個點掌握沿邊前乙個點的資訊,傳遞x輪後,任意乙個點恰好掌握沿邊反向前進x條邊的路徑上的所有點的資訊,要聽到自己的資訊,也就是在環上走一圈。這樣就把題目抽象為找...