引水工程

时间限制: 3 Sec  内存限制: 128 MB
提交: 11  解决: 6
[提交][状态][讨论版]

题目描述

南水北调工程是优化水资源配置、促进区域协调发展的基础性工程,是新中国成立以来投资额最大、涉及面最广的战略性工程,事关中华民族长远发展。“南水北调工程”,旨在缓解中国华北和西北地区水资源短缺的国家战略性工程。就是把中国长江流域丰盈的水资源抽调一部分送到华北和西北地区。我国南涝北旱,南水北调工程通过跨流域的水资源合理配置,促进南北方经济、社会与人口、资源、环境的协调发展。

整个工程分东线、中线、西线三条调水线。东线工程位于东部,因地势低需抽水北送至华北地区。中线工程从汉水与其最大支流丹江交汇处的丹江口水库引水,自流供水给黄淮海平原大部分地区,20多座大中城市;西线工程在青藏高原上,由长江上游向黄河上游补水。

现在有N个区域需要建设水资源工程,它们可以自建水库解决缺水问题,也可以从已有水源的地区建立管道引水过来。当然,这些建设都需要大量投资。

你能不能给出一个优化水资源配置方案,在保证每个区域都能用上水的前提下,使得整个引水工程费用最低。

输入

第一行: K 表示有多少组测试数据。

接下来对每组测试数据:

第1行: N 表示有N个区域( 1<=N<=300 )

第2 行: W1 W2 …. WN Wi表示第i个区域自建水库需要的费用

再有N行: Pi1 Pi2 …. Pin Pij表示建立第i个区域与第j个区域引水管道的费用

输出

对于每组测试数据,输出占一行,即建立整个引水工程的最小费用。

样例输入

1
5
5 4 4 3 6
0 2 2 2 2
2 0 3 3 3
2 3 0 4 5
2 3 4 0 1
2 3 5 1 0

样例输出

10

这道题的思路(我觉得有漏洞):在全部都自己建水的基础上,选最便宜的点建水,然后借这个点向外松弛。
虽然我AC了,但是发现有一组我自己编的样例过不了,那就是
1
3
11 11 10
0 1 1
1 0 1
10 10 0
答案应该是12,但是我的代码是21,网上很多代码都是21,这其实源于 选最便宜的点建水 这一步有问题,因此我觉得应该每个点都作为起点试一下,但TLM了。
真正的解法应该用克鲁斯卡尔。 下面是AC代码(因为题目不严谨而AC)prim解法
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#define inf 0x3f3f3f3f
using namespace std;
int a[];
int e[][];
bool v[];
int n;
int prim()
{
memset(v, , sizeof(v));
int sum = ;
while ()
{
int mbu = inf;
int k, i;
k = -;
for (i = ; i <= n; i++)//先都建水,找出当前建水费用最少的点
{
if (v[i]==&&(k==-||a[i] < a[k]))
{
k = i;
}
}
if (k == -) break;
sum = sum + a[k];
v[k] = ;//模拟删除改点
for (i = ; i <= n; i++)
{
a[i] = min(a[i], e[k][i]);//用该点松弛
}
}
return sum;
}
int main()
{
int t;
cin >> t;
while (t--)
{
cin >> n;
memset(e, inf, sizeof(e));
int i;
for (i = ; i <= n; i++)
{
cin >> a[i];
}
int j;
for (i = ; i <= n; i++)
{
for (j = ; j <= n; j++)
{
cin >> e[i][j];
}
}
cout << prim() << endl;
}
}

下面是克鲁斯卡尔(Kruskal)解法,我的样例也能过

 巧妙地把在i建水设为e[0][i]

思路,将自建水库 i 需要的费用转化为边0---->i .

然后用并查集算法求点 0到n的最小生成树即可。

代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct Edge
{
int u;
int v;
int cost;
}e[];
int map[][],c[],n,p[];
int comp(Edge e1,Edge e2)
{
return e1.cost<e2.cost;
}
int find(int x) //找父节点
{
if(p[x]!=x)
{
p[x]=find(p[x]);
}
return p[x];
}
bool bin(int x,int y) //将x,y添加至一个集合
{
int g,h;
g=find(x);
h=find(y);
if(g==h)
return false;
p[g]=h;
return true;
}
bool judge() //判断是否所有点都在一个集合
{
int i,count=;
for(i=;i<=n;i++)
{
if(p[i]==i)
count++;
if(count>)
return false;
}
return true;
}
int main()
{
int t,k,i,j,x,res;
scanf("%d",&t);
while(t--)
{
res=;
k=;
scanf("%d",&n);
for(i=;i<=n;i++)
p[i]=i;
for(i=;i<=n;i++)
{
scanf("%d",&x);
e[k].u=;
e[k].v=i;
e[k++].cost=x;
}
for(i=;i<=n;i++)
for(j=;j<=n;j++)
{
scanf("%d",&x);
e[k].u=i;
e[k].v=j;
e[k++].cost=x;
}
sort(e,e+k,comp);
for(i=;i<k;i++)
{
if(bin(e[i].u,e[i].v))
res+=e[i].cost;
if(judge())
break;
}
printf("%d\n",res);
}
return ;
}
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<set>
using namespace std;
#define mem(x,y) memset(x,y,sizeof(x))
#define SI(x) scanf_s("%d",&x)
#define SL(x) scanf_s("%lld",&x)
#define PI(x) printf("%d",x)
#define PL(x) printf("%lld",x)
#define P_ printf(" ")
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);
typedef long long LL;
const int MAXN = ;
struct Node
{
int u, v, w;
void init(int x = , int y = , int z = )/*:u(x),v(y),w(z)*/
{
u = x; v = y; w = z;
}
friend bool operator < (Node a, Node b)
{
return a.w<b.w;
}
}dt[];
int ans;
int pre[MAXN];
int find(int x)
{
return pre[x] = x == pre[x] ? x : find(pre[x]);
}
void merge(Node a)
{
int f1 = find(a.u), f2 = find(a.v);
if (f1 != f2)pre[f1] = f2, ans += a.w;
}
int main()
{
int K, N;
SI(K);
while (K--)
{
SI(N);
int x, k = ;
for (int i = ; i <= N; i++)
for (int j = ; j <= N; j++)
{
SI(x);
if (i<j)
{
dt[k++].init(i, j, x);
}
}
sort(dt, dt + k);
//for(int i=0;i<k;i++)printf("%d %d %d\n",dt[i].u,dt[i].v,dt[i].w);
for (int i = ; i <= N; i++)pre[i] = i;
ans = ;
for (int i = ; i<k; i++)merge(dt[i]);
printf("%d\n", ans);
}
return ;
}
下面是能过这组样例但是超时的代码
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#define inf 0x3f3f3f3f
using namespace std;
int a[];
int e[][];
bool v[];
int u[];
int n;
int prim()
{
int sum = ;
while ()
{
int mbu = inf;
int k, i;
k = -;
for (i = ; i <= n; i++)//先都建水,找出当前建水费用最少的点
{
if (v[i]==&&(k==-||a[i] < a[k]))
{
k = i;
}
}
if (k == -) break;
sum = sum + a[k];
v[k] = ;//模拟删除改点
for (i = ; i <= n; i++)
{
a[i] = min(a[i], e[k][i]);//用该点松弛
}
}
return sum;
}
int main()
{
int t;
cin >> t;
while (t--)
{
cin >> n;
memset(e, inf, sizeof(e));
int i;
for (i = ; i <= n; i++)
{
cin >> u[i];
}
int j;
for (i = ; i <= n; i++)
{
for (j = ; j <= n; j++)
{
cin >> e[i][j];
}
}
int mm = inf;
int s1;
memset(v, , sizeof(v));
for (i = ; i <= n; i++) a[i] = u[i];
s1 = prim();
if (s1 < mm) mm = s1;
for (i = ; i <= n; i++)//我加了这一步
{
int j;
for (j = ; j <= n; j++) a[j] = u[j];
memset(v, , sizeof(v));
v[i] = ;//这一点确定不自己建水
s1 = prim();
if (s1 < mm) mm = s1;
v[i] = ;//回退
}
cout << mm << endl;
}
}
//1 3
//10 10 11
//0 1 1
//1 0 1
//10 10 0
//

@太年轻

感谢这位游客,告诉我了不能过我的样例的真相:

其实这题没有说明白,但是观察样例可以
看出每个 i 到 j 的值与 j 到 i 的值是相等的,题目中没有明说这一点,
但是那样写都过了说明测试数据没有不相等的情况。
其实克鲁斯卡尔和Prim都是相通的,能用克鲁斯卡尔就一定能用Prim.
比如这题,我们将错就错,题目没有说管道是单向的,那么拿博主造的
样例来说,在连边的时候较长的边就废弃不用了,用Prim时只需在
连边的时候加一句判断条件即可,这样博主的样例Prim也能过了,
至于克鲁斯卡尔为什么能过,以为sort()排序已经把长的边排到了
后面,实际上长边根本没有用到,和Prim前面的剔除长边道理相通。
话说回来,如果道路是单向的,那么Prim就不能剔除边,但这时用
克鲁斯卡尔也是错的,因为克鲁斯卡尔不会考虑方向,比如存在两条边
a-->b c-->b 若用克鲁斯卡尔加入并查集,则a,c便在一个并查集里,
但实际上a,c是不相通的。


zufe oj 引水工程( 巧妙地把在i建水设为e[0][i])的更多相关文章

  1. zzuoj 10409 10409: D.引水工程

    10409: D.引水工程 Time Limit: 2 Sec  Memory Limit: 128 MBSubmit: 96  Solved: 34[Submit][Status][Web Boar ...

  2. 第八届河南省赛D.引水工程(kruthcra+prime)

    D.引水工程 Time Limit: 2 Sec  Memory Limit: 128 MB Submit: 118  Solved: 41 [Submit][Status][Web Board] D ...

  3. Nyoj 引水工程(最小生成树)

    描述 南水北调工程是优化水资源配置.促进区域协调发展的基础性工程,是新中国成立以来投资额最大.涉及面最广的战略性工程,事关中华民族长远发展.“南水北调工程”,旨在缓解中国华北和西北地区水资源短缺的国家 ...

  4. 河南省第八届ACM省赛---引水工程

    引水工程 时间限制:2000 ms  |  内存限制:65535 KB 难度: 描述 南水北调工程是优化水资源配置.促进区域协调发展的基础性工程,是新中国成立以来投资额最大.涉及面最广的战略性工程,事 ...

  5. nyoj 1239——引水工程——————【最小生成树 prim】

    引水工程 时间限制:2000 ms  |  内存限制:65535 KB 难度:3   描述 南水北调工程是优化水资源配置.促进区域协调发展的基础性工程,是新中国成立以来投资额最大.涉及面最广的战略性工 ...

  6. POJ-2421Constructing Roads,又是最小生成树,和第八届河南省赛的引水工程惊人的相似,并查集与最小生成树的灵活与能用,水过~~~

    Constructing Roads Time Limit: 2000MS   Memory Limit: 65536K               Description There are N v ...

  7. ZUFE OJ 2288 God Wang I

    Description God Wang 是ZUFE的神犇,有一天他想到一种神奇的变换,并且将它命名为GodW变换 对于一个数字n,该变换后的值GodW(n)为,先令X=n 第一步,如果X为个位数,G ...

  8. ZUFE OJ 2301 GW I (3)

    Description GW 是ZUFE的神犇,有一天他想到一种神奇的变换,并且将它命名为GW变换 对于一个数字n,该变换后的值GW(n)为,先令X=n 第一步,如果X为个位数,GW(n)=X,否则执 ...

  9. ZUFE OJ 2145 05机关图

    Description Ink最近得到了一张藏宝图,这张图上共有n个藏宝室,但因为年代久远藏宝图上的路已经模糊不清,于是Ink找到了智慧的Pseudo,Pseudo告诉Ink,这个宝藏中每两个藏宝室之 ...

随机推荐

  1. 量身打造自己的MyEclipse(多图)

    迎新年 贺元旦MyEclipse推新版 在线订购低至 7.5 折!截止1月31号(活动期间在线下单的客户才可享受此优惠,过期恢复原价) 立即抢购 1.量身打造你自己的MyEclipse MyEclip ...

  2. php_os 检查php运行环境

    if(strtolower(PHP_OS)=='linux'){ $tests['os']['state']="good"; $tests['os']['message']='OS ...

  3. Android RIL的java框架

    Android RIL的Java部分也被分为了两个模块,RIL模块与Phone模块.其中RIL模块负责进行请求以及相应的处理,它将直接与RIL的原声代码进行通信.而Phone模块则向应用程序开发者提供 ...

  4. Python中的import

    模块(module):用来从逻辑(实现一个功能)上组织Python代码(变量.函数.类),本质就是*.py文件.文件是物理上组织方式"module_name.py",模块是逻辑上组 ...

  5. DelaunayTriangulation_VoronoiDiagram_using_OpenCV的实现

    前言 最近project中有关于delaunay的实现问题,查找资料,看到learnopencv这个网站,有很多peoject的实现,本文主要是实现Delaunay Triangulation and ...

  6. 了解dto概念,什么是DTO

    了解dto概念   此博文收集整理了一些主流的文章对于DTO模式的解读,他们大体相似而又各有所不同.对于设计模式的解读也是一个仁者见仁智者见智的事情,不过设计模式往往都是前辈们在遇到一类特定的问题下而 ...

  7. 拒绝了对对象 '****'(数据库 '******',所有者 '***')的 SELECT 权限

    数据库(xxx) --->安全性---->架构---->dbo(属性)--->权限--->添加--->浏览-->public 添加 select 等您需要的权 ...

  8. (4)格式化输出(%用法和format用法以及区别)

    %s用法(%s的用法是写多少个,后面就要传多少个) format用法(基本语法是通过{}和:来代替%.format函数可以接受不限个参数,位置可以不按顺序) 形式一(顺序填坑{}) >>& ...

  9. $data[$i++]+=2;不等于$data[$i++]=$data[$i++]+2;

    $data=array(1,2,3,4); $i=1; $data[$i++]+=2; var_dump($data); echo $i; //输出:array(1,4,3,4) 和 2 $data= ...

  10. Vquery PHP 简单爬虫类

    http://www.thinkphp.cn/topic/36693.html 在使用php进行网页抓取的时候你有没有感觉到用起来比较麻烦呢?目前我还没有发现php有这样针对网页抓取的类,每次用到这个 ...