【题解】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 }

原文地址:https://www.cnblogs.com/moyujiang/p/11213343.html

时间: 2024-10-10 01:04:56

【题解】P2916 [USACO08NOV]安慰奶牛Cheering up the Cow-C++的相关文章

[USACO08NOV]安慰奶牛Cheering up the Cow

这个题一看就是最小生成树,但是这题关键是确定边权. 首先为了安慰奶牛,一定要遍历每个奶牛并且回到起点,所以每条边会被经过两次,而为了通过这条边必须和两端点奶牛谈话,因此要再加上两端点的c值.综上(i,j)边权为l(i,j)  * 2 + c_i + c_j. #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #define N 10010 #define M 1000

题解 P2915 [USACO08NOV]奶牛混合起来Mixed Up Cows

题解 P2915 [USACO08NOV]奶牛混合起来Mixed Up Cows 题目链接 数据规模16-20的都是状压 如果要每一位都压序号的话空间肯定是不够的,所以每一位只能是0或1.1表示有这头牛,0表示没有这头牛.显然每个位置的选择和他两边的牛有关,所以我们就可以定义这样的状态: f[i][j]表示使用集合i的牛,其中最后一头牛的序号为j时的总方案数.答案从f[(1 << n) - 1][n]累加即可. 转移也比较好想,从i中枚举选出倒数第二头牛,作为子状态的最后一头牛,注意边界情况.

bzoj1232[Usaco2008Nov]安慰奶牛cheer*

bzoj1232[Usaco2008Nov]安慰奶牛cheer 题意: 给出n个节点的带权图,第i个节点ci.现在你要在这个图中选出一棵树和一个起点,然后你要从起点出发到达所有的节点(不能跳点)再回到起点,经过边的时间为边权,每经过一个点就要花等同于点权的时间(即使这个点已经过).问如何使时间最短.n≤10000. 题解: 每条边的边权为这条边原来的边权加两个端点的点权(因为每个点都要经过两次),然后做最小生成树. 代码: 1 #include <cstdio> 2 #include <

算法训练 安慰奶牛

[原][Usaco Nov08 Gold] 安慰奶牛 2014-5-26阅读159 评论0 Description Farmer John变得非常懒, 他不想再继续维护供奶牛之间供通行的道路. 道路被用来连接N (5 <= N <= 10,000)个牧场, 牧场被连续地编号为1..N. 每一个牧场都是一个奶牛的家. FJ计划除去P(N-1 <= P <= 100,000)条道路中尽可能多的道路, 但是还要保持牧场之间的连通性. 你首先要决定那些道路是需要保留的N-1条道路. 第j条

1232: [Usaco2008Nov]安慰奶牛cheer

1232: [Usaco2008Nov]安慰奶牛cheer Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 612  Solved: 431[Submit][Status] Description Farmer John变得非常懒, 他不想再继续维护供奶牛之间供通行的道路. 道路被用来连接N (5 <= N <= 10,000)个牧场, 牧场被连续地编号为1..N. 每一个牧场都是一个奶牛的家. FJ计划除去P(N-1 <= P <=

蓝桥杯 安慰奶牛

算法训练 安慰奶牛 时间限制:1.0s   内存限制:256.0MB 锦囊1 使用最小生成树算法. 锦囊2 将每条边(a, b)的权值Lj改变为2Lj+Ca+Cb,然后使用最小生成树来计算. 问题描述 Farmer John变得非常懒,他不想再继续维护供奶牛之间供通行的道路.道路被用来连接N个牧场,牧场被连续地编号为1到N.每一个牧场都是一个奶牛的家.FJ计划除去P条道路中尽可能多的道路,但是还要保持牧场之间 的连通性.你首先要决定那些道路是需要保留的N-1条道路.第j条双向道路连接了牧场Sj和

蓝桥杯训练 安慰奶牛 (Kruskal MST)

算法训练 安慰奶牛 时间限制:1.0s   内存限制:256.0MB 问题描述 Farmer John变得非常懒,他不想再继续维护供奶牛之间供通行的道路.道路被用来连接N个牧场,牧场被连续地编号为1到N.每一个牧场都是一个奶牛的家.FJ计划除去P条道路中尽可能多的道路,但是还要保持牧场之间 的连通性.你首先要决定那些道路是需要保留的N-1条道路.第j条双向道路连接了牧场Sj和Ej(1 <= Sj <= N; 1 <= Ej <= N; Sj != Ej),而且走完它需要Lj的时间.

蓝桥杯试题 算法训练 安慰奶牛

算法训练 安慰奶牛 时间限制:1.0s   内存限制:256.0MB 问题描述 Farmer John变得非常懒,他不想再继续维护供奶牛之间供通行的道路.道路被用来连接N个牧场,牧场被连续地编号为1到N.每一个牧场都是一个奶牛的家.FJ计划除去P条道路中尽可能多的道路,但是还要保持牧场之间 的连通性.你首先要决定那些道路是需要保留的N-1条道路.第j条双向道路连接了牧场Sj和Ej(1 <= Sj <= N; 1 <= Ej <= N; Sj != Ej),而且走完它需要Lj的时间.

蓝桥杯 - 安慰奶牛 (最小生成树)

题目传送:蓝桥杯 - 安慰奶牛 思路:先算好边的权值,为本来的边的权值的两倍加上两个点的权值,再进行kruskal,因为边数较大,不宜采用prim AC代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define LL long long #define INF 0x7fffffff const in