【最小生成树】安慰员工

来源:互联网 发布:背托福单词软件 编辑:程序博客网 时间:2024/05/07 13:45
安慰员工(cheer.pas/c/cpp)
 
【题目描述】
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



这道题很水,是裸题,但是大部分人都没看出来。

欧拉回路,在树上有一个性质,就是每一条边必须走两次。(至于为什么我想到这点,是因为当时学LCA的原因,所以知道这点)

每一条边走两次,而这条边上的每个点分别走一次,因此容易发现,一个点走的次数就是它的出度,但是我们不用管这个,只需要把点的权值加到边权值的2倍上即可。

注意,根节点访问次数要多加1,所以很简单,找一个权值最小的点作根即可。


#include <cstdio>#include <algorithm>#define min(a,b) ((a)<(b)?(a):(b))using std::sort;struct Edge{long u;long v;long c;bool operator<(const Edge& e2)const{return c<e2.c;}};Edge edge[100010];long fa[10010];long C[10010];long getint(){long rs=0;bool sgn=1;char tmp;do tmp = getchar();while (!isdigit(tmp)&&tmp-'-');if (tmp == '-'){tmp=getchar();sgn=0;}do rs=(rs<<3)+(rs<<1)+tmp-'0';while (isdigit(tmp=getchar()));return sgn?rs:-rs;}long getroot(long u){if (fa[u] == u)return u;return fa[u] = getroot(fa[u]);}void merge(long a,long b){fa[getroot(a)] = getroot(b);}int main(){freopen("cheer.in","r",stdin);freopen("cheer.out","w",stdout);long n = getint();long p = getint();for (long i=1;i<n+1;i++){fa[i] = i;C[i] = getint();}for (long i=1;i<p+1;i++){long u = getint();long v = getint();long c = getint();edge[i].u = u;edge[i].v = v;edge[i].c = c*2+C[v]+C[u];}sort(edge+1,edge+1+p);long ans = 0;for (long i=1;i<p+1;i++){long u = edge[i].u;long v = edge[i].v;if (getroot(u)!=getroot(v)){ans += edge[i].c;merge(u,v);}}long minc = 0x3f3f3f3f;for (long i=1;i<n+1;i++){minc = min(minc,C[i]);}printf("%ld",ans+minc);return 0;}



原创粉丝点击