1. 程式人生 > >牛客練習賽32-D-MST+tarjin割邊

牛客練習賽32-D-MST+tarjin割邊

連結:https://ac.nowcoder.com/acm/contest/272/D
來源:牛客網

題目描述

小p和他的朋友約定好去遊樂場遊玩,但是他們到了遊樂場後卻互相找不到對方了。
遊樂場可以看做是一張n個點,m條道路的圖,每條道路有邊權wi,表示第一次經過該道路時的花費(第二次及以後經過時花費為0)。
現在,小p要去找他的朋友,但他的朋友行蹤很詭異,小p總是要遍歷完這n個點才能找到他,同時小p希望總花費最小。
找到朋友的方案可能不唯一(具體看樣例解釋),小p想知道在這所有的方案中,有多少條邊在每個方案中都會被經過。

輸入描述:

第一行兩個整數n, m. p,分別表示點數,邊數,小p的初始位置。

接下來m行,每行兩個整數u, v, w表示從u到v有一條無向邊,邊權為w。

輸出描述:

輸出一個整數k,表示必須經過的邊的數量。

    

 


連通圖沒怎麼學過很傷= =
  看了很久這個題解大概明白了思路,按照kruskal的方法,按照相同的w分類來討論哪些邊是必不可少的,如果在當前的圖中e是割邊,
就說明付出w的代價使得圖的連通性增強了1,顯然這條邊必不可少。如果不是割邊,無論他會不會使得連通性增加我們都不必考慮。
  譬如w1<w2<w3在進行w2輪次時,如果兩個端點已經聯通這條邊顯然沒必要,如果未聯通且是割邊,那他就是必不可少的邊。因為按照
貪心的思想必須這麼做。
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=200050;
 4 int root,sum=1,dfn[maxn],low[maxn],ans[maxn],f[maxn];
 5 int getf(int u){return f[u]==u?u:f[u]=getf(f[u]);}
 6 struct Ed{
 7     int u,v,w;
 8     bool operator<(const Ed &A)const{
 9         return
w<A.w; 10 } 11 }E[maxn]; 12 struct Edge{int v,id,next;}e[maxn*2]; 13 int first[maxn],tot; 14 void add(int u,int v,int id){ 15 e[tot].v=v; 16 e[tot].id=id; 17 e[tot].next=first[u]; 18 first[u]=tot++; 19 } 20 void tarjin(int u,int last){ 21 dfn[u]=low[u]=sum++; 22 for(int i=first[u];~i;i=e[i].next){ 23 int v=e[i].v; 24 if(i==(1^last))continue; 25 if(dfn[v]){ 26 low[u]=min(low[u],dfn[v]); 27 } 28 else{ 29 tarjin(v,i); 30 low[u]=min(low[u],low[v]); 31 if(low[v]>dfn[u])ans[e[i].id]=1; 32 } 33 } 34 } 35 int main(){ 36 int i,j,n,m,p,u,v,w; 37 scanf("%d%d%*d",&n,&m); 38 tot=0; 39 memset(first,-1,sizeof(first)); 40 for(i=1;i<=n;++i)f[i]=i; 41 for(i=0;i<m;++i){ 42 scanf("%d%d%d",&E[i].u,&E[i].v,&E[i].w); 43 } 44 sort(E,E+m); 45 for(i=0;i<m;++i){ 46 j=i; 47 while(j+1<m&&E[j+1].w==E[i].w)j++; 48 tot=0; 49 for(int k=i;k<=j;++k){ 50 int fu=getf(E[k].u),fv=getf(E[k].v); 51 if(fu!=fv){ 52 add(fu,fv,k); 53 add(fv,fu,k); 54 } 55 } 56 for(int k=i;k<=j;++k){ 57 int fu=getf(E[k].u),fv=getf(E[k].v); 58 if(fu==fv || dfn[fu]) continue; 59 tarjin(fu,-1); 60 } 61 for(int k=i;k<=j;++k){ 62 int fu=getf(E[k].u),fv=getf(E[k].v); 63 if(fu==fv)continue; 64 first[fu]=first[fv]=-1; 65 dfn[fu]=dfn[fv]=0; 66 f[fu]=fv; 67 } 68 i=j; 69 } 70 int h=0; 71 for(i=0;i<m;++i)h+=ans[i]; 72 cout<<h<<endl; 73 return 0; 74 }