[USACO08NOV]安慰奶牛Cheering up the Cow BZOJ 1232 Kruskal

Farmer John变得非常懒, 他不想再继续维护供奶牛之间供通行的道路. 道路被用来连接N (5 <= N <= 10,000)个牧场, 牧场被连续地编号为1..N. 每一个牧场都是一个奶牛的家. FJ计划除去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)的时间和奶牛交谈. 你每个晚上都会在同一个牧场(这是供你选择的)过夜, 直到奶牛们都从悲伤中缓过神来. 在早上起来和晚上回去睡觉的时候, 你都需要和在你睡觉的牧场的奶牛交谈一次. 这样你才能完成你的交谈任务. 假设Farmer John采纳了你的建议, 请计算出使所有奶牛都被安慰的最少时间. 对于你前10次的提交, 你的程序会在一部分正式的测试数据上运行, 并且返回运行的结果.

Sample Output176 Hint


Input

* 第 1 行: 用空格隔开的两个整数N和P * 第 2..N+1 行: 第i+1行包含了一个整数: C_i * 第 N+2..N+P+1 行: 第 N+j+1 行包含用空格隔开的三个整数: S_j, E_j 和 L_j

Output

第 1 行: 一个整数, 所需要的总时间(包含和在你所在的牧场的奶牛的两次谈话时间).

Sample Input5 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
 
感觉自己语文太差,题目刚开始没怎么读懂.........
本来就想着将点权合并到边上去,但还是害怕读错题目.....
其实就是一个 kruskal 的题目;
我们将点权以及边权*2的和算为该边的新权值,然后跑一边 Kruskal即可;最后加上权值最小的点即可;
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<bitset>
#include<ctime>
#include<deque>
#include<stack>
#include<functional>
#include<sstream>
//#include<cctype>
//#pragma GCC optimize("O3")
using namespace std;
#define maxn 200005
#define inf 0x3f3f3f3f
#define INF 9999999999
#define rdint(x) scanf("%d",&x)
#define rdllt(x) scanf("%lld",&x)
#define rdult(x) scanf("%lu",&x)
#define rdlf(x) scanf("%lf",&x)
#define rdstr(x) scanf("%s",x)
typedef long long  ll;
typedef unsigned long long ull;
typedef unsigned int U;
#define ms(x) memset((x),0,sizeof(x))
const long long int mod = 1e9 + 7;
#define Mod 1000000000
#define sq(x) (x)*(x)
#define eps 1e-3
typedef pair<int, int> pii;
#define pi acos(-1.0)
const int N = 1005;
#define REP(i,n) for(int i=0;i<(n);i++)
typedef pair<int, int> pii;
inline ll rd() {
    ll x = 0;
    char c = getchar();
    bool f = false;
    while (!isdigit(c)) {
        if (c == '-') f = true;
        c = getchar();
    }
    while (isdigit(c)) {
        x = (x << 1) + (x << 3) + (c ^ 48);
        c = getchar();
    }
    return f ? -x : x;
}

ll gcd(ll a, ll b) {
    return b == 0 ? a : gcd(b, a%b);
}
ll sqr(ll x) { return x * x; }

/*ll ans;
ll exgcd(ll a, ll b, ll &x, ll &y) {
    if (!b) {
        x = 1; y = 0; return a;
    }
    ans = exgcd(b, a%b, x, y);
    ll t = x; x = y; y = t - a / b * y;
    return ans;
}
*/



ll qpow(ll a, ll b, ll c) {
    ll ans = 1;
    a = a % c;
    while (b) {
        if (b % 2)ans = ans * a%c;
        b /= 2; a = a * a%c;
    }
    return ans;
}

int n, m;
struct node {
    int u, v, w;
}edge[maxn];

int valnode[maxn];

bool cmp(node a, node b) {
    return a.w < b.w;
}
int tot;
int fa[maxn];
int findfa(int x) {
    if (x == fa[x])return x;
    return fa[x] = findfa(fa[x]);
}

int kruskal() {
    int ans = 0;
    for (int i = 0; i <= n; i++)fa[i] = i;
    sort(edge , edge + tot, cmp);
    int cnt = 0;
    for (int i = 0; i < tot; i++) {
        int u = edge[i].u; int v = edge[i].v;
        int w = edge[i].w;
        if (findfa(u) != findfa(v)) {
            fa[findfa(u)] = findfa(v);
            ans += w; cnt++;
            if (cnt == n - 1)break;
        }
    }
    return ans;
}

void addedge(int u, int v, int w) {
    edge[tot].u = u; edge[tot].v = v; edge[tot++].w = w * 2 + valnode[u] + valnode[v];
}
int main()
{
    //ios::sync_with_stdio(0);
    rdint(n); rdint(m); int minn = inf;
    for (int i = 1; i <= n; i++)rdint(valnode[i]), minn = min(minn, valnode[i]);
    for (int i = 1; i <= m; i++) {
        int u, v, w; rdint(u); rdint(v); rdint(w);
        addedge(u, v, w); addedge(v, u, w);
    }
    cout << kruskal()+minn << endl;
    return 0;
}

 

posted @ 2018-11-19 09:15  NKDEWSM  阅读(248)  评论(0编辑  收藏  举报