【NOIP practice】BSOJ 2998修復公路 最小生成樹

2988 -- 【基礎試題】修復公路
Description
  A地區在地震過後,連接所有村莊的公路都造成了損壞而無法通車。政府派人修復這些公路。
  給出A地區的村莊數N,和公路數M,公路是雙向的。並告訴你每條公路的連着哪兩個村莊,並告訴你什麼時候能修完這條公路。問最早什麼時候任意兩個村莊能夠通車,即最早什麼時候任意兩條村莊都存在至少一條修復完成的道路(可以由多條公路連成一條道路)
Input
  第1行兩個正整數N,M(N<=1000,M<=100000)
  下面M行,每行3個正整數x, y, t,告訴你這條公路連着x,y兩個村莊,在時間t時能修復完成這條公路。(x<=N,y<=N,t<=100000)
Output
  如果全部公路修復完畢仍然存在兩個村莊無法通車,則輸出-1,否則輸出最早什麼時候任意兩個村莊能夠通車。
Sample Input
4 4
1 2 6
1 3 4
1 4 5
4 2 3
Sample Output
5


這是一道純粹的最小生成樹。
爲什麼呢?將時間看做邊權,要在一個圖裏面找出讓每個點連接的最小方案——最小生成樹(“且包含原圖中的所有 n 個結點,並且有保持圖連通的最少的邊”)。

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
struct node
{
	int fr,to,val;
}w[500005];
int n,m;
int h[500005]={0},cnt=0,ans=0;
int prt[500005]={0};
void Addarc(int x,int y,int v)
{
	cnt++;w[cnt].fr=x;w[cnt].to=y;w[cnt].val=v;
}
bool cmp(node x,node y)
{
	return x.val<y.val;
}
void init()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
	{
		int a,b,c;
		scanf("%d%d%d",&a,&b,&c);
		Addarc(a,b,c);
		Addarc(b,a,c);
	}
}
int Getfa(int x)
{
	if(x==prt[x])return x;
	return prt[x]=Getfa(prt[x]); 
}
void K()
{
	int ct=0;
	for(int i=1;i<=n;i++)prt[i]=i;
	for(int i=1;i<=2*m;i++)
	{
		int f1=Getfa(w[i].fr),f2=Getfa(w[i].to);
		if(f1!=f2)
		{
			prt[f1]=f2;
			ans=max(ans,w[i].val);
			ct++;
		}
		if(ct==n-1)break;
	}
	if(ct==n-1)printf("%d\n",ans);
	else printf("-1\n");
}
int main(){

	init();
	sort(w+1,w+2*m+1,cmp);//按邊權排序,單向邊,雙向邊,共2m條邊 
	K();
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章