【题解】P2916 [USACO08NOV]安慰奶牛Cheering up the Cow-C++

原题传送门

这道题用最小生成树来完成,我选用的是kruskal(克鲁斯卡尔)来完成。
这道题目在克鲁斯卡尔模板的基础上,有变动的地方只有2处:
1.因为必须从一个点出发,而最小生成树最后会让所有点都连通,所以最优的是从c[i]值最低的点出发,所以最后的total要加上最小的c[i]值。
2.因为这道题目的权值很特殊,它包含了2*路的长度(来回走两次)+起点的c[i]+终点的c[i](这个也要花费时间),在读入的时候直接处理就可以了。
代码就贴在这,因为考虑可能有些题目会卡输入,用了快读,介意的自己改一下就行了(滑稽)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,p,c[100010],fa[100010];
 4 int read()
 5 {
 6    int x=0,f=1;
 7    char ch=getchar();
 8    while(ch<'0'||ch>'9'){
 9        if(ch=='-')
10            f=-1;
11        ch=getchar();
12    }
13    while(ch>='0'&&ch<='9'){
14        x=(x<<1)+(x<<3)+(ch^48);
15        ch=getchar();
16    }
17    return x*f;
18 }
19 struct node
20 {
21     int u,v,w;
22     node(){}
23     node(int vv,int ww)
24     {
25         v=vv,w=ww;
26     }
27 }g[100010];
28 bool cmp(node a,node b)
29 {
30     return a.w<b.w;
31 }
32 void init()
33 {
34     for(int i=1;i<=n;i++)
35         fa[i]=i;
36 }
37 int get(int x)
38 {
39     if(fa[x]==x)return x;
40     else return fa[x]=get(fa[x]);
41 }
42 bool merge(int x,int y)
43 {
44     int r1=get(x),r2=get(y);
45     if(r1==r2)return 0;
46     fa[r1]=r2;
47     return 1;
48 }
49 int main()
50 {
51     cin>>n>>p;
52     init();
53     int minc=0x3f3f3f3f;
54     for(int i=1;i<=n;i++)
55     {
56         c[i]=read();
57         minc=min(minc,c[i]); 
58     } 
59     for(int i=1;i<=p;i++)
60         g[i].u=read(),g[i].v=read(),g[i].w=read()*2+c[g[i].u]+c[g[i].v];
61     sort(g+1,g+1+p,cmp);
62     int cnt=0;
63     int total=0;
64     for(int i=1;i<=p;i++)
65     {
66         if(merge(g[i].u,g[i].v))
67         {
68             cnt++;
69             total+=g[i].w;
70         }
71     }
72     cout<<total+minc<<endl;
73     return 0;
74 }

 

posted @ 2019-07-19 15:06  摸鱼酱  阅读(237)  评论(0编辑  收藏  举报