题目背景:考完试回来发现了一道原题QAQ
题目背景
John的农场缺水了!!!
题目描述
农民John 决定将水引入到他的n(1<=n<=300)个牧场。他准备通过挖若
干井,并在各块田中修筑水道来连通各块田地以供水。在第i 号田中挖一口井需要花费W_i(1<=W_i<=100,000)元。连接i 号田与j 号田需要P_ij (1 <= P i , j P_{i,j} Pi,j <= 100,000 , P j , i P_{j,i} Pj,i= P i , j P_{i,j} Pi,j)元。
请求出农民John 需要为使所有农场都与有水的农场相连或拥有水井所需要的钱数。
输入输出格式
输入格式:
第1 行为一个整数n。
第2 到n+1 行每行一个整数,从上到下分别为W_1 到W_n。
第n+2 到2n+1 行为一个矩阵,表示需要的经费(P_ij)。
输出格式:
只有一行,为一个整数,表示所需要的钱数。
输入输出样例
输入样例#1:
4
5
4
4
3
0 2 2 2
2 0 3 3
2 3 0 4
2 3 4 0
输出样例#1:
9
说明
John等着用水,你只有1s时间!!!
做法:另类的最小生成树啊就是!
为什么在考场上没想出来??
只要设立一个虚点用来存点权就好了!!
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std ;
int read(){ //快读
int x = 0 ;int f = 1 ; char s= getchar() ;
while(s>'9'||s<'0') {if(s=='-')f=-1;s=getchar();}
while(s<='9'&&s>='0') {x=x*10+(s-'0');s=getchar();}
return x*f ;
}
int n ;
int w[500] ;
struct dy{//结构体
int x , y , z ;
}a[200010];int t ;
void add(int x , int y,int z) {
a[++t].x = x ;
a[t].y = y ;
a[t].z = z ;
}int vis[500][500] ;
int fa[500] ;
int find(int x) {
if(fa[x] != x ) fa[x] = find(fa[x]) ;
return fa[x] ;
}
void unionn(int x , int y ) {
x = find(x) ;
y = find(y) ;
fa[x] = y ;
}
int cmp(dy x , dy y) {
return x.z < y.z ;
}
int main(){
n = read() ;
for(int i = 1 ; i <= n ; i++) {
w[i] = read() ;
add(0,i,w[i]) ;//存放点权
}
for(int i = 1 ; i <= n ; i ++) {
for(int j = 1 ; j <= n ; j ++) {
int x ;
x = read() ;
if(i == j) continue ;//为了防止出现BUG,当有向图来存
if(vis[i][j]) continue ;
vis[i][j] = 1 ;
add(i,j,x) ;
}
}
int tot = 0, k = 0 ;
sort(a+1,a+1+t,cmp) ;
for(int i = 0 ; i <= n ; i ++) fa[i] = i ;
for(int i = 1 ; i <= t ; i ++) {//kruskal 算法
if(find(a[i].x) != find(a[i].y)) {
unionn(a[i].x , a[i].y) ;
k ++ ;
tot += a[i].z ;
}
if(k == n) break ;
}
printf("%d\n",tot) ;
return 0;
}
完结散花!!!