描述
南水北调工程是优化水资源配置、促进区域协调发展的基础性工程,是新中国成立以来投资额最大、涉及面最广的战略性工程,事关中华民族长远发展。“南水北调工程”,旨在缓解中国华北和西北地区水资源短缺的国家战略性工程。就是把中国长江流域丰盈的水资源抽调一部分送到华北和西北地区。我国南涝北旱,南水北调工程通过跨流域的水资源合理配置,促进南北方经济、社会与人口、资源、环境的协调发展。
整个工程分东线、中线、西线三条调水线。东线工程位于东部,因地势低需抽水北送至华北地区。中线工程从汉水与其最大支流丹江交汇处的丹江口水库引水,自流供水给黄淮海平原大部分地区,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
- 来源
- 第八届河南省程序设计大赛
- 上传者
- hnu_acm
题解: 找到建立水库的最小值,以此建立最小生成树.......蒟蒻啊 ....自己刚开始的思路想错了.....
WA代码:
1 #include <vector> 2 #include <map> 3 #include <set> 4 #include <algorithm> 5 #include <iostream> 6 #include <cstdio> 7 #include <cmath> 8 #include <cstdlib> 9 #include <string> 10 #include <cstring> 11 #include <queue> 12 using namespace std; 13 #define INF 0x3f3f3f3f 14 #define MAX 100010 15 16 int n,ans,minn; 17 int quyu[333],vis[333],dis[333]; 18 int mp[333][333]; 19 20 void prim() 21 { 22 memset(vis,0,sizeof(vis)); 23 memset(dis,INF,sizeof(dis)); 24 dis[1]=0; 25 ans=0; 26 dis[0]=INF; 27 while(true){ 28 int m=0; 29 for(int i=1; i<=n; i++){ 30 if(!vis[i] && dis[i]<dis[m]) 31 m=i; 32 } 33 if(m==0) 34 break; 35 vis[m]=1; 36 ans+=dis[m]; 37 for(int i=1; i<=n; i++) 38 dis[i]=min(dis[i],mp[m][i]); 39 } 40 } 41 42 void init() 43 { 44 memset(mp,INF,sizeof(mp)); 45 memset(quyu,0,sizeof(quyu)); 46 minn=INF; 47 } 48 49 int main() 50 { 51 int t; 52 scanf("%d",&t); 53 while(t--){ 54 init(); 55 scanf("%d",&n); 56 for(int i=0; i<n; i++){ 57 scanf("%d",&quyu[i]); 58 if(minn>quyu[i]) 59 minn=quyu[i]; 60 } 61 for(int i=1; i<=n; i++) 62 for(int j=1; j<=n; j++){ 63 scanf("%d",&mp[i][j]); 64 } 65 prim(); 66 printf("%d ",ans+minn); 67 } 68 }
AC代码:
1 #include <vector> 2 #include <map> 3 #include <set> 4 #include <algorithm> 5 #include <iostream> 6 #include <cstdio> 7 #include <cmath> 8 #include <cstdlib> 9 #include <string> 10 #include <cstring> 11 #include <queue> 12 using namespace std; 13 #define INF 0x3f3f3f3f 14 #define MAX 100010 15 16 int n,ans,minn; 17 int quyu[333],vis[333],dis[333]; 18 int mp[333][333]; 19 20 void prim() 21 { 22 memset(vis,0,sizeof(vis)); 23 memset(dis,INF,sizeof(dis)); 24 for(int i=0;i<=n;i++) 25 dis[i]=mp[0][i]; 26 ans=0; 27 //dis[0]=INF; 28 while(true){ 29 int m=0; 30 for(int i=1; i<=n; i++){ 31 if(!vis[i] && dis[i]<dis[m]) 32 m=i; 33 } 34 if(m==0) 35 break; 36 vis[m]=1; 37 ans+=dis[m]; 38 for(int i=1; i<=n; i++) 39 dis[i]=min(dis[i],mp[m][i]); 40 } 41 } 42 43 void init() 44 { 45 memset(mp,INF,sizeof(mp)); 46 memset(quyu,0,sizeof(quyu)); 47 minn=INF; 48 } 49 50 int main() 51 { 52 int t; 53 scanf("%d",&t); 54 while(t--){ 55 init(); 56 scanf("%d",&n); 57 for(int i=1; i<=n; i++){ 58 scanf("%d",&mp[0][i]); 59 } 60 for(int i=1; i<=n; i++) 61 for(int j=1; j<=n; j++){ 62 scanf("%d",&mp[i][j]); 63 } 64 prim(); 65 printf("%d ",ans); 66 } 67 }
别人的克鲁斯卡尔A的:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #define Maxsize 310 5 #define INF 0x3f3f3f3f 6 int n; 7 int p[Maxsize][Maxsize]; 8 int par[Maxsize]; 9 int rank[Maxsize]; 10 void init() 11 { 12 memset(p,0x3f,sizeof(p)); 13 for(int i=0;i<=n;i++) 14 { 15 par[i]=i; 16 rank[i]=0; 17 } 18 } 19 int find(int x) 20 { 21 if(par[x]==x) 22 return x; 23 else return par[x]=find(par[x]); 24 } 25 void unite(int x,int y) 26 { 27 x=find(x); 28 y=find(y); 29 if(x==y) 30 return; 31 if(rank[x]<rank[y]) 32 par[x]=y; 33 else 34 { 35 par[y]=x; 36 if(rank[x]==rank[y]) 37 rank[x]++; 38 } 39 } 40 bool same(int x,int y) 41 { 42 return find(x)==find(y); 43 } 44 int FindTree() 45 { 46 int res=0; 47 int a,b; 48 for(;;) 49 { 50 int min=INF; 51 for(int i=0;i<=n;i++) 52 for(int j=i+1;j<=n;j++) 53 { 54 if(min>p[i][j]&&(!same(i,j))) 55 { 56 min=p[i][j]; 57 a=i;b=j; 58 } 59 } 60 if(min==INF) 61 break; 62 // printf("%d ",min); 63 res+=p[a][b]; 64 unite(a,b); 65 } 66 return res; 67 } 68 int main() 69 { 70 int K; 71 int i,j; 72 scanf("%d",&K); 73 while(K--) 74 { 75 scanf("%d",&n); 76 init(); 77 for(i=1;i<=n;i++) 78 { 79 scanf("%d",&p[0][i]); 80 p[i][0]=p[0][i]; 81 } 82 for(i=1;i<=n;i++) 83 for(j=1;j<=n;j++) 84 scanf("%d",&p[i][j]); 85 printf("%d ",FindTree()); 86 } 87 return 0; 88 }