A. 修路 2014新生暑假個人排位賽06
題目描述
小弱的學校很喜歡修路,現在給你一張他學校的地圖,地圖上有n個點和m條雙向邊,每條邊代表一條路,這條路有可能是暢通,也有可能正在修路。大家都知道修路使得交通很不方便。所有小弱很想學校快快的把路修好,使得他能夠很輕鬆的到達主樓915去刷題。但考慮到學校的施工能力有限,小弱想讓你幫他算出學校需要集中力量馬上修好的最少路數,使得他能夠從學校任意點出發,在不經過正在施工的路下到達主樓(編號爲1)。
輸入格式
有多組數據。
每組數據以n( 1<=n<=10000), m(1<=m<=200000)開頭。接下來一行有m行數。每行有三個數,對應於u, v, s,分別爲這條路的兩端點(編號從1到n)和路況,s = 0代表暢通, s = 1 代表正在修路。輸入保證圖是連通圖。
輸出格式
對每組數據輸出對應的最少路數。
輸入樣例
3 2
1 2 0
1 3 1
3 2
1 2 0
1 3 0
3 2
1 2 1
1 3 1
輸出樣例
1
0
2
思路:這道題沒有給出權值,直接就要求你求出最少加的。那最少加的就是每一次先把同一個聯通塊的並在一起,然後若有新的聯通塊就加進去就肯定是最短的。
代碼:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<vector>
#define maxn 20000
#define maxm 500000
//#define LOCAL
using namespace std;
int n,m,x,y,v,cnt,num,ans;
int father[maxn];
int from[maxm],to[maxm];
int getfather(int x)
{
if(father[x]==x)return x;
return father[x]=getfather(father[x]);
}
void Union(int x,int y,int v)
{
int f1=getfather(x);
int f2=getfather(y);
if(f1!=f2){num++;if(v==1)ans++;father[f2]=f1;}
}
int main()
{
#ifdef LOCAL
freopen("input.txt","r",stdin);
#endif // LOCAL
while(scanf("%d%d",&n,&m)==2)
{
cnt=0;num=1;ans=0;
//memset(h,-1,sizeof(h));
for(int i=1;i<=n;i++)father[i]=i;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&v);
if(v==0)Union(x,y,0);
else{cnt++;from[cnt]=x;to[cnt]=y;}
}
if(cnt==0){printf("0\n");continue;}
for(int i=1;i<=cnt;i++)
{
Union(from[i],to[i],1);
if(num==n)break;
}
printf("%d\n",ans);
}
return 0;
}