最小树形图(有向图的最小生成树)

求最小树形图

算法:朱刘算法

下面纠正几个易错错误和较难理解的地方(可结合程序判断)

1.所缩的环为为所选择的边所形成的环,并不是图中所有的环。

2.缩环后可能形成新的环。

3.缩环后减权不改变最小树形图的大小,减权是为了删边(所删的边在这之前已经加了,但并不属于最小树形图,所以要删去)。

相关的题目 poj3164

代码

 1 #include <iostream>
 2 #include <cstdlib>
 3 #include <cstdio>
 4 #include <cmath>
 5 #include <string>
 6 #include <cstring>
 7 #include <algorithm>
 8 using namespace std;
 9 
10 const int Inf=2000000000;
11 const int Max=105;
12 struct Point
13 {
14     double x,y;
15 }p[Max];
16 struct node
17 {
18     int u,v;
19     double w;
20 }e[Max*Max];
21 int pre[Max],id[Max],vis[Max],n,m;
22 double Minc[Max];
23 
24 double dis(Point a,Point b)
25 {
26     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
27 }
28 
29 double Directed_MST(int root,int V,int E)
30 {
31     int u,v,cnt;
32     double ret=0;
33     while(true)
34     {
35         for(int i=0; i<V; i++)    Minc[i]=Inf;
36         for(int i=0; i<E; i++)
37         {
38             u=e[i].u;v=e[i].v;
39             if(e[i].w<Minc[v]&&u!=v)
40                 pre[v]=u,Minc[v]=e[i].w;
41         }
42         for(int i=0; i<V; i++)
43         {
44             if(i==root)    continue;
45             if(Minc[i]==Inf)    return -1;
46         }
47         cnt=0;Minc[root]=0;
48         memset(id,-1,sizeof(id));
49         memset(vis,-1,sizeof(vis));
50         for(int i=0; i<V; i++)
51         {
52             ret+=Minc[i];v=i;
53             while(vis[v]!=i&&id[v]==-1&&v!=root)    vis[v]=i,v=pre[v];
54             if(v!=root&&id[v]==-1)
55             {
56                 for(int u=pre[v]; u!=v; u=pre[u])
57                     id[u]=cnt;
58                 id[v]=cnt++;
59             }
60         }
61         if(cnt==0)    break;
62         for(int i=0; i<V; i++)
63             if(id[i]==-1)
64                 id[i]=cnt++;
65         for(int i=0; i<E; i++)
66         {
67             u=e[i].u,v=e[i].v;
68             e[i].u=id[u],e[i].v=id[v];
69             if(id[u]!=id[v])    e[i].w-=Minc[v];
70         }
71         V=cnt;root=id[root];
72     }
73     return ret;
74 }
75 
76 int main()
77 {
78     while(scanf("%d%d",&n,&m)==2)
79     {
80         for(int i=0; i<n; i++)    scanf("%lf%lf",&p[i].x,&p[i].y);
81         for(int i=0; i<m; i++)
82         {
83             scanf("%d%d",&e[i].u,&e[i].v);
84             e[i].u--,e[i].v--;
85             if(e[i].u!=e[i].v)    e[i].w=dis(p[e[i].u],p[e[i].v]);
86             else    e[i].w=Inf;
87         }
88         double ans=Directed_MST(0,n,m);
89         if(ans==-1)    printf("poor snoopy\n");
90         else    printf("%.2f\n",ans);
91     }
92     return 0;
93 }

 

posted @ 2020-07-14 16:35  ycy123456  Views(537)  Comments(0Edit  收藏  举报