最小生成树——取水

原题:zjnu 1213

题意

给n个地方的凿井花费,每个地方和其他地方的造水管花费,求把所有地方都通水的最小花费

解析

对于凿井花费,我们看成和0结点(不存在)的通水花费即可,然后用最小生成树的模板求连接所有结点的最小花费(因为所有结点包括0结点,所以不会出现没有水的错误)。

代码

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include 
#include
#define D long long
#define F double
#define MAX 0x7fffffff
#define MIN -0x7fffffff
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back  
#define mk make_pair  
#define fi first  
#define se second  
#define pill pair  
#define for1(i,a,b) for(int i=a;i<=b;i++)
#define for2(i,a,b) for(int i=a;i>=b;i--)
#define ini(n) scanf("%d",&n)
#define inll(n) scanf("%lld",&n)
#define outisp(n) printf("%d ",n)
#define outllsp(n) printf("%lld ",n)
#define outiel(n) printf("%d\n",n)
#define outllel(n) printf("%lld\n",n)
using namespace std; 
#define N 500100 
#define MOD ((int)1e9+7)
#define random(a,b) (rand()%(b-a+1)+a)
#define stop Sleep(2000)
#define CLS system("cls")
const string el="\n";
const string elel="\n\n";
const string sp=" ";
const string spsp="  ";
const string tab="\t";

int n;int now=0;
int fa[500];
struct node{
    int x,y,v;
    bool operator<(const node &a)const{
        return v250000];

int fin(int x){
    return fa[x]==x?x:fa[x]=fin(fa[x]);
}

int main(){
    ini(n);for1(i,1,n){
        ini(e[++now].v),e[now].x=0,e[now].y=i,fa[i]=i;
    }
    for1(i,1,n){
        for1(j,1,n){
            int mid;ini(mid);
            if(j<=i)continue;
            e[++now].x=i,e[now].y=j,e[now].v=mid;
        }
    }
    int ans=0;
    sort(e+1,e+1+now);
    for1(i,1,now){
        int fa1=fin(e[i].x),fa2=fin(e[i].y);
        if(fa1!=fa2){
            fa[fa1]=fa2;ans+=e[i].v;
        }
    }
    outiel(ans);
} 

你可能感兴趣的:(数据结构)