[USACO08NOV]安慰奶牛Cheering up the Cow

Posted lijilai-oi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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 10000000
using namespace std;
int n,m;
struct qwq
{
    int x,y,val;
    bool operator < (const qwq &a) const
    {
        return val < a.val;
    }
}e[M];
int fa[N],siz[N];
int find(int x)
{
    if(fa[x] != x) fa[x] = find(fa[x]);
    return fa[x];
}
void merge(int x,int y)
{
    if(siz[x] > siz[y]) swap(x,y); 
    siz[y] += siz[x];
    fa[x] = y;
    return;
}
int kruskal()
{
    sort(e + 1,e + 1 + m);
    int tot = 0,ans = 0;    
    for(int i = 1;i <= m;i++)
    {
        int x = find(e[i].x),y = find(e[i].y);
        if(x != y)
        {
            merge(x,y);
            ans += e[i].val;
            tot++;
        }
        if(tot == n - 1) break;
    }
    return ans;
}
int c[N];
using namespace std;
int main()
{
    scanf("%d %d",&n,&m);
    int minn = 1000000;
    for(int i = 1;i <= n;i++) 
    {
        scanf("%d",&c[i]);
        minn = min(c[i],minn);
        fa[i] = i;
        siz[i] = 1;
    }
    for(int i = 1;i <= m;i++) 
    {
        scanf("%d %d %d",&e[i].x,&e[i].y,&e[i].val);
        e[i].val = (e[i].val << 1) + c[e[i].x] + c[e[i].y];
    }
    printf("%d\n",kruskal() + minn);
    return 0;
}

 

以上是关于[USACO08NOV]安慰奶牛Cheering up the Cow的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1232[Usaco2008Nov]安慰奶牛cheer*

BZOJ1232[Usaco2008Nov]安慰奶牛cheer 最小生成树

bzoj 1232 [Usaco2008Nov]安慰奶牛cheer

bzoj 1232: [Usaco2008Nov]安慰奶牛cheer最小生成树

BZOJ 1232 [Usaco2008Nov]安慰奶牛cheer:最小生成树树上dfs性质

洛谷 P2916 [USACO08NOV]为母牛欢呼Cheering up the C…