卧薪尝胆,厚积薄发。
      
    
            USACO2008 OCT 灌水
        
        
        Description:
把一块土地进行灌水有两种方法,从其他农田饮水,或者这块土地建造水库。 建造一个水库需要花费
$w_i$
,连接两块土地需要花费
$P_{ij}$
。计算
$Farmer$
 
$John$
所需的最少代价
$1\le N\le 300$
Solution:
首先每个点都有两种决策,从别的点引水或者新建,所以我们可以增加一个超级源点。然后每个源点向每个点都连边,每条边的边权是在这个点建立水库的费用,然后点之间互相连边,最后一次最小生成树就可以了。
Code:
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int n;
#define MAXN 310
struct edge
{
	int u,v,w;
}e[MAXN * MAXN * 2];
int edgenum = 0;
void add(int a,int b,int c)
{
	++edgenum;e[edgenum].u = a;e[edgenum].v = b;e[edgenum].w = c;
	return;
}
bool cmp(edge x,edge y){return x.w < y.w;}
int f[MAXN];
int find(int x){return (x == f[x] ? x : f[x] = find(f[x]));}
int main()
{
	scanf("%d",&n);
	int a;
	for(int i = 1;i <= n;++i)
	{
		scanf("%d",&a);
		add(i,n + 1,a);
	}
	for(int i = 1;i <= n;++i)
	{
		for(int j = 1;j <= n;++j)
		{
			scanf("%d",&a);
			add(i,j,a);
		}
	}
	sort(e + 1,e + 1 + edgenum,cmp);
	for(int i = 1;i <= n;++i)f[i] = i;
	int ans = 0;
	for(int i = 1;i <= edgenum;++i)
	{
		int p = find(e[i].u),q = find(e[i].v);
		if(p == q)continue;
		f[p] = q;
		ans += e[i].w;
	}
	cout << ans << endl;
	return 0;
}
 In tag:
图论-kruskal
          In tag:
图论-kruskal 
          
        
        Copyright © 2020
        
          wjh15101051
        
      
      ღゝ◡╹)ノ♡
     Date: Tue Jul 17 00:07:27 CST 2018
          Date: Tue Jul 17 00:07:27 CST 2018
           In Category:
          In Category:
           
         Timeline
            Timeline
           About
            About
           Toolbox
            Toolbox
           Friends
              Friends