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

描述

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

整个工程分东线、中线、西线三条调水线。东线工程位于东部,因地势低需抽水北送至华北地区。中线工程从汉水与其最大支流丹江交汇处的丹江口水库引水,自流供水给黄淮海平原大部分地区,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\n",ans+minn);
67     }
68 }        
View Code

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\n",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\n",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\n",FindTree());
86     }
87     return 0;
88 }
View Code

 

posted @ 2016-03-28 23:25  Vmetrio  阅读(318)  评论(0编辑  收藏  举报