題解 SHOI2010 最小生成樹

2022-02-19 20:25:38 字數 1762 閱讀 5634

題目大意:

在乙個合法的連通圖中,每條邊都有乙個邊權,我們欽定一條邊。然後對圖進行一些操作:將某一條邊的權值+1或-1。請問至少多少次後可以使欽定的邊出現在該圖的最小生成樹中。

luogu傳送門:[shoi2010]最小生成樹

解題思路:

說實話:我們一定要跳出題目的侷限性,畢竟網路流是屬於圖演算法。

我們考慮,為什麼我們欽定的邊會不在最小生成樹上,很簡單,有更多比它更小的邊。並且,能夠更新我們欽定邊的邊一定會和我們欽定的邊成環(我們考慮kruscal的實現過程,如果想不明白,可以看看 嚴格次小生成樹 )。

在這道題中更為簡單,由上述條件,我們只需要對於每一條比我們欽定邊target小的邊建立一條權值為

權值 = t[ target ].val - t[ i ].val + 1的流邊即可。然後轉化為最小割模型即可。

模型轉化:

我很想把它提出來講。

我們既然要找到一條符合的邊,那麼就是要讓最小生成樹經過欽定邊target,經過的前提就是可以到達target邊上兩點的其他路徑都沒有target更優,那麼,然這些邊增大即可。這樣一想,感覺就是讓這兩點之間的其他路徑都比target邊的邊權大。

我們對這些原本更小的邊都計算於target邊權的差值,然後跑最小割。

口糊合法性:

1.這些邊都小於target的邊權,如果更大,那麼它本身就不可以能優於target邊,就不可能在target之前進入最小生成樹

2.由1可知,上述建出的流圖中無負邊權(流量為負),所以流演算法是可行的。(最小割 = 最大流 )

3.如果target就在原本的最小生成樹上,那麼流圖是不連通的,所以出題人是卡不了的。

注:樓主作死寫了hlpp,完全可以用dinic打,而且lll優化後還更快一些,當然隨機資料hlpp絕對有時間上的優勢。

ac code:

#includeusing namespace std;

const int maxn = 100010 , inf = ( 1 << 30 ) ;

inline int read()

while(g>='0'&&g<='9')

return s*w;

}int tot = 1 , to[ maxn ] , nex[ maxn ] , head[ 10005 ] , w[ maxn ] , n , m , t , s , target ;

int d[ 10005 ] , e[ 10005 ] , h[ 10005 ] , numh[ maxn ] ;

bool v[ maxn ] ;

struct apt[ maxn ];

void add( int x , int y , int z )

void relabel( int u )

}struct cmp}}

}return;

}void push_(int u)

if( !e[u] )break;}}

}int hlpp()}}

while(!q.empty())

}relabel( u ) ;

numh[ h[ u ] ]++ ;

q.push( u ) ;

v[ u ] = true ;}}

return e[ t ] ;

} void prepare()

int main()

}cout

}

SHOI2010 最小生成樹

嘟嘟嘟 這道題的切入點在於模型的轉化。令第 lab 條邊連線的兩個點分別為 x,y 根據kruskal演算法,我們排完序加邊的時候,在執行第 lab 條邊之前,都要保證 x,y 不連通。這就很像最小割了。所以我們把邊權小於 w 的都拿來建圖,那邊權是啥咧?題中說的除了一條邊其餘的都減1,那不就相當於...

SHOI2010 最小生成樹(貪心)(最小割)

首先這個全域性 1可以等價成單點 1。考慮建樹的kruskal演算法。發現其實就是要求在加入權值小於等於這條邊的那些邊的時候,s,t s,ts,t不連通。顯然最小割。include define ll long long define re register define cs const cs i...

最小生成樹 次小生成樹

一 最小生成樹 說到生成樹首先要解釋一下樹,樹是乙個聯通的無向無環圖,多棵樹的集合則被稱為森林。因此,樹具有許多性質 1.兩點之間的路徑是唯一的。2.邊數等於點數減一。3.連線任意兩點都會生成乙個環。對於乙個無向聯通圖g的子圖,如果它包含g的所有點,則它被稱為g的生成樹,而各邊權和最小的生成樹則被稱...