引水工程 Kruskal + Prim

Kruskal题解 : 以案例输入为例 有五个缺水地区 , 这个个缺水地区之间建立联系的费用已经给出 并且之间水库的费用也已经给出 , 自己水库也已看为 是另一个 点 , 这样就有了 6 个点 , 这六个点彼此之间可以建立联系 , 总共形成 5 条边 , 将这 6 个点连接起来 , 这样就符合了题意 , 也可以更好的 用Kruskal 解决 这一个问题 ,  我们可以让  这五个点 建立一个 到 0 的 距离关系 , 这样就有 0 - 6 六个点了 , 下面附上 实现代码

从水库和各个点之间的通道是单向的 , 

 

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<math.h>
 4 #include<iostream>
 5 #include<limits.h>
 6 #include<algorithm>
 7 #include<queue>
 8 #include<vector>
 9 #include<set>
10 #include<stack>
11 #include<string>
12 #include<sstream>
13 #include<map>
14 #include<cctype>
15 using namespace std;
16 int n,m,minn,father[305],sum,tem[305];
17 struct node
18 {
19     int x,y,l;
20 }a[90005];
21 bool cmp(node a,node b)
22 {
23     return a.l<b.l;
24 }
25 int find(int x)                      //  做了时间上的优化 ,但是 在空间复杂度上比较高
26 {
27     if(x!=father[x])
28         father[x]=find(father[x]);
29     sum++;
30     return father[x];
31 }
32 bool merge(int x,int y)    // 做了时间复杂度上的优化  让并查集的 深度尽量  浅
33 {
34     int sum1,sum2;
35     sum=0;
36     x=find(x);
37     sum1=sum;        //    x  的深度
38     sum=0;
39     y=find(y);
40     sum2=sum;       //    y   的深度
41     if(x!=y)
42     {
43         if(sum1>sum2)
44             father[y]=x;
45         else
46             father[x]=y;
47         return true;
48     }
49     else
50         return false;
51 }
52 int main()              //  先用  Dijkstra 做一次   // Dijkstra 是 根据边来做的
53 {
54     int t;
55     scanf("%d",&t);
56     while(t--)
57     {
58         scanf("%d",&n);
59         for(int i=0;i<=n;i++)
60             father[i]=i;
61         int q=0;
62         for(int i=0;i<=n;i++)
63         {
64             for(int j=1;j<=n;j++)
65             {
66                 int e;
67                 scanf("%d",&e);
68                 a[q].x=j;
69                 a[q].y=i;
70                 a[q].l=e;
71                 q++;
72             }
73         }
74         int m=n*n,sum3=0,count1=0;
75         sort(a,a+q,cmp);
76         for(int i=0;i<q;i++)
77         {
78             if(merge(a[i].x,a[i].y))
79             {
80                     sum3+=a[i].l;
81                     count1++;
82             }
83             if(count1==n)           //  如果边数等于 所有需要连接的 点数-1的话 就跳出去
84                 break;
85         }
86         printf("%d\n",sum3);
87     }
88     return 0;
89 }

 

Prim 题解 : Prim 是根据 点之间的关系 去 构成最小生成树的  ,   做题的思路和上面 Kruskal 处理之间水库一样 下面附上实现代码   .

 

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<math.h>
 4 #include<iostream>
 5 #include<limits.h>
 6 #include<algorithm>
 7 #include<queue>
 8 #include<vector>
 9 #include<set>
10 #include<stack>
11 #include<string>
12 #include<sstream>
13 #include<map>
14 #include<cctype>
15 using namespace std;
16 int a[305][305],visited[305],dis[305];
17 int main()
18 {
19     int t,n;
20     scanf("%d",&t);
21     while(t--)
22     {
23         scanf("%d",&n);
24         for(int i=0;i<=n;i++)
25         {
26             dis[i]=INT_MAX;
27             for(int j=0;j<=n;j++)
28             {
29                 a[i][j]=INT_MAX;
30             }
31         }
32         memset(visited,0,sizeof(visited));
33         for(int i=0;i<=n;i++)
34         {
35             for(int j=1;j<=n;j++)
36             {
37                 scanf("%d",&a[i][j]);  //
38                 if(i==0)
39                     a[j][i]=a[i][j];  //  OK  !
40             }
41         }
42         int n1=n,minn,j,b=0,sum=0;
43         visited[0]=1;  //从水库开始吧
44         while(n1--)  //  一共 n+1 个点 需要 n 个边
45         {
46             minn=INT_MAX;
47             for(int i=0;i<=n;i++)
48             {
49                 if(b!=i&&a[b][i]<dis[i]&&!visited[i])  //       visited  控制 是否成环
50                 {
51                     dis[i]=a[b][i];  //  如果不是自己到自己 并且 现在该点到 以前该点比已经确定的集合的距离短的话 ,那么就刷新距离
52                 }
53             }
54             for(int i=0;i<=n;i++)
55             {
56                 if(minn>dis[i]&&!visited[i])
57                 {
58                     minn=dis[i];
59                     j=i;
60                 }
61             }
62             visited[j]=1;
63             b=j;
64             sum+=minn;
65         }
66         printf("%d\n",sum);
67     }
68     return 0;
69 }

 

 

 

 

 

posted @ 2016-04-12 13:56  X-POWER  阅读(259)  评论(0编辑  收藏  举报