Kruskal-BZOJ-1601- [Usaco2008 Oct]灌水

2023-10-17 07:18

本文主要是介绍Kruskal-BZOJ-1601- [Usaco2008 Oct]灌水,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Description

Farmer John已经决定把水灌到他的n(1<=n<=300)块农田,农田被数字1到n标记。把一块土地进行灌水有两种方法,从其他农田饮水,或者这块土地建造水库。 建造一个水库需要花费wi(1<=wi<=100000),连接两块土地需要花费Pij(1<=pij<=100000,pij=pji,pii=0). 计算Farmer John所需的最少代价。
Input

*第一行:一个数n

*第二行到第n+1行:第i+1行含有一个数wi

*第n+2行到第2n+1行:第n+1+i行有n个被空格分开的数,第j个数代表pij。
Output

*第一行:一个单独的数代表最小代价.
Sample Input
4

5

4

4

3

0 2 2 2

2 0 3 3

2 3 0 4

2 3 4 0

Sample Output
9

输出详解:

Farmer John在第四块土地上建立水库,然后把其他的都连向那一个,这样就要花费3+2+2+2=9


题解:
由题分析可知,其实这是一个无向带权图,要求的只是一个MST而已,同时鉴于有w[i]这个东西,我选择多建立一个点0,w[i]就成了p[0][i]。


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#define MAXN 305
#define INF 0x3f3f3f3f
using namespace std;
int n;
typedef struct edge{long long int w;int s,t;
}Edge;
Edge E[100000];
long long int father[MAXN];
long long int w[MAXN];
long long int out,total;
int f(int now)
{while(father[now]!=now) now=father[now];return now;
}
bool c(const Edge a,const Edge b)
{return a.w<b.w;
}int main()
{cin >> n;out=0,total=0;father[0]=0;for(int i=1;i<=n;i++){father[i]=i;scanf("%lld",&E[total].w);E[total].s=0;E[total++].t=i;}long long int tmp;for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){scanf("%lld",&tmp);if(i==j)continue;E[total].s=i;E[total].t=j;E[total++].w=tmp;}sort(E+0,E+total,c);for(long long int i=0;i<total;i++){int fa=f(E[i].s),fb=f(E[i].t);if(fa==fb)continue;father[fa]=fb;out+=E[i].w;}cout << out << endl;return 0;}

这篇关于Kruskal-BZOJ-1601- [Usaco2008 Oct]灌水的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/223813

相关文章

C语言-数据结构 克鲁斯卡尔算法(Kruskal)邻接矩阵存储

相比普里姆算法来说,克鲁斯卡尔的想法是从边出发,不管是理解上还是实现上都更简单,实现思路:我们先把找到所有边存到一个边集数组里面,并进行升序排序,然后依次从里面取出每一条边,如果不存在回路,就说明可以取,否则就跳过去看下一条边。其中看是否是回路这个操作利用到了并查集,就是判断新加入的这条边的两个顶点是否在同一个集合中,如果在就说明产生回路,如果没在同一个集合那么说明没有回路可以加入

【BZOJ】1324 Exca王者之剑 最大权独立集

传送门:【BZOJ】1324  Exca王者之剑 题目分析:赤裸裸的最大权独立集。。。最小割解决 代码如下: #include <cstdio>#include <vector>#include <cstring>#include <algorithm>using namespace std ;#define REP( i , a , b ) for ( int

【BZOJ】1026: [SCOI2009]windy数 数位DP

传送门:【BZOJ】1026: [SCOI2009]windy数 题目分析:数位DP水题。 代码如下: #include <stdio.h>#include <cstring>#include <algorithm>#define rep( i , a , b ) for ( int i = a ; i < b ; ++ i )#define For( i ,

【BZOJ】2152: 聪聪可可 点分治

传送门:【BZOJ】2152: 聪聪可可 题目分析:记录权值和%3的路径的个数。。。然后去重。。没了。。 代码如下: #include <vector>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std ;typedef lo

BZOJ 2440 2301 莫比乌斯应用

http://www.lydsy.com/JudgeOnline/problem.php?id=2440 Description 小 X 自幼就很喜欢数。但奇怪的是,他十分讨厌完全平方数。他觉得这些 数看起来很令人难受。由此,他也讨厌所有是完全平方数的正整数倍的数。然而 这丝毫不影响他对其他数的热爱。  这天是小X的生日,小 W 想送一个数给他作为生日礼物。当然他不能送一 个小X讨厌

BZOJ 3732: Network(最小生成树+倍增)

题目链接 题意:给出一个图,每个询问的格式是:A B,表示询问从A点走到B点的所有路径中,最长的边最小值是多少 很明显最终查询的边一定是在最小生成树里面的,先跑出最小生成树,然后,可以树链剖分,也可以使用倍增来计算 #include<bits/stdc++.h>using namespace std;#define cl(a,b) memset(a,b,sizeof(a))#define

hdu-1863畅通工程 最小生成树克鲁斯卡尔算法kruskal(并查集实现)prim普利姆算法实现

畅通工程 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 16994    Accepted Submission(s): 7134 Problem Description 省政府“畅通工程”的目标是使全省任何两个村

最小生成树 - Kruskal算法

kruskal算法---求稀疏图的最小生成树 步骤 1,将所有边按权重从大到小排序,调用系统的 sort 函数 2,枚举每条边 a、b ,权重c         if(a、b 不联通) 就将这条边加入集合中 输入格式 第一行包含两个整数n和m。 接下来m行,每行包含三个整数u,v,w,表示点u和点v之间存在一条权值为w的边。输出格式 共一行,若存在最小生成树,则输出一个整数,表示最小生成

BZOJ 2038 小Z的袜子(hose) (莫队离线)

题目地址:BZOJ 2038 裸的莫队算法。 代码如下: #include <iostream>#include <string.h>#include <math.h>#include <queue>#include <algorithm>#include <stdlib.h>#include <map>#include <set>#include <stdio.h>#in

BZOJ 2152 聪聪可可 (树上点分治)

题目地址:BZOJ 2152 找有多少对权值和为3的倍数的点。最简单的点分治。 代码如下: #include <iostream>#include <string.h>#include <math.h>#include <queue>#include <algorithm>#include <stdlib.h>#include <map>#include <set>#incl