1. 程式人生 > >noip模擬題 慰問員工 cheer

noip模擬題 慰問員工 cheer

【題目描述】
LongDD 變得非常懶, 他不想再繼續維護供員工之間供通行的道路. 道路被用來連
接 N(5 <= N <= 10,000)個房子, 房子被連續地編號為 1..N. 每一個房子都是一個
員工的家. LongDD 計劃除去 P(N-1 <= P <= 100,000)條道路中儘可能多的道路, 但
是還要保持房子之間的連通性. 你首先要決定那些道路是需要保留的 N-1 條道路.
第 j 條雙向道路連線了房子 S_j 和 E_j (1 <= S_j <= N; 1 <= E_j <= N; S_j != E_j),
而且走完它需要 L_j (0 <= L_j <= 1,000)的時間. 沒有兩個房子 是被一條以上的道
路所連線.
員工們非常傷心, 因為她們的交通系統被削減了. 你需要到每一個員工的住處去安
慰她們. 每次你到達第 i 個房子的時候(即使你已經到過), 你必須花去 C_i (1 <=
C_i <= 1,000)的時間和員工交談.
你需要從某一個房子出發( 這是供你選擇的),並 最終 回到 這個 房子。期間,你要經
過每個房子至少一次,並且當你經過某個房子的時候,你必須和這個房子裡的員工
交談(即使你已經到過).
假設 LongDD 採納了你的建議, 請計算出使所有員工都被安慰的最少時間.
【輸入格式】
* 第 1 行: 用空格隔開的兩個整數 N 和 P
* 第 2..N+1 行: 第 i+1 行包含了一個整數: C_i
* 第 N+2..N+P+1 行: 第 N+j+1 行包含用空格隔開的三個整數: S_j, E_j 和 L_j
【輸入樣例】
5 7
10
10
20
6
30
1 2 5
2 3 5
2 4 12
3 4 17
2 5 15
3 5 6
4 5 12
【輸出格式】
* 第 1 行: 一個整數, 所需要的總時間(包含和在你所在的房子的員工的兩次談話
時間).
【輸出樣例】

176

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
int father[1000005];
struct pp
{
	int u,v,w;
}e[1000005];
int find(int x)
{
	if(father[x]!=x)
	father[x]=find(father[x]);
	return father[x];
}
void UN(int x,int y)
{
	int a,b;
	a=find(x);
	b=find(y);
	father[a]=b;
}
bool cmp(pp a,pp b)
{
	return a.w<b.w;
}
int n,m,c[100005],k(0),kk(0),ans(0),minn(0x7f),o(0);
int  main()
{
	freopen("cheer.in","r",stdin);
	freopen("cheer.out","w",stdout);
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++)
	{
	scanf("%d ",&c[i]);
	minn=min(minn,c[i]);
    }
	for(int i=1;i<=m;i++)
	{
		int x ,y, z;
		scanf("%d %d %d",&x,&y,&z);
		k++;
		e[k].u=x;
		e[k].v=y;
		e[k].w=z*2+c[x]+c[y];
	}
	sort(e+1,e+1+m,cmp);
	for(int i=1;i<=n;i++)
	father[i]=i;
	while(o<n-1)
	{
		kk++;
		if(find(e[kk].u)!=find(e[kk].v))
		{
		ans+=e[kk].w;
		UN(e[kk].u,e[kk].v);
		o++;
	    }
	}
	printf("%d\n",ans+minn);
	return 0;
}

最小生成樹的一道題目。