首页 > 编程语言 > 详细

最小树型图 [朱刘算法]

时间:2019-10-18 00:52:46      阅读:50      评论:0      收藏:0      [点我收藏+]

参考博客 点我ヾ(^▽^*)))

// 例题 poj 3164

 1 /*
 2  * @Promlem: 
 3  * @Time Limit: ms
 4  * @Memory Limit: k
 5  * @Author: pupil-XJ
 6  * @Date: 2019-10-16 15:17:03
 7  * @LastEditTime: 2019-10-16 15:55:18
 8  */
 9 #include<cstdio>
10 #include<cmath>
11 #include<cstring>
12 #include<algorithm>
13 using namespace std;
14 const int INF = 0x3f3f3f3f;
15 const int MAXN = 1000+5;
16 const int MAXM = MAXN*MAXN;
17 
18 struct node {
19     int from, to;
20     double cost;
21 } edge[MAXM];
22 
23 int n, m;// n个点 m条有向边
24 int pre[MAXN];// 储存父节点
25 int vis[MAXN];// 标记作用
26 int id[MAXN];// id[i]记录节点i所在环的编号
27 double in[MAXN];// in[i]记录i入边最小的权值
28 
29 double zhuliu(int root) {
30     double res = 0;
31     while(1) {
32         for(int i = 0; i != n; ++i) in[i] = INF;
33         for(int i = 0; i != m; ++i) {
34             node e = edge[i];
35             if(e.from != e.to && e.cost < in[e.to]) {
36                 pre[e.to] = e.from;
37                 in[e.to] = e.cost;
38             }
39         }
40         for(int i = 0; i != n; ++i) 
41             if(i != root && in[i] == INF) 
42                 return -1;
43         int tn = 0;
44         memset(id, -1, sizeof(id));
45         memset(vis, -1, sizeof(vis));
46         in[root] = 0;
47         for(int i = 0; i != n; ++i) {
48             res += in[i];
49             int v = i;
50             while(vis[v] != i && id[v] == -1 && v != root) {
51                 vis[v] = i;
52                 v = pre[v];
53             }
54             if(v != root && id[v] == -1) {
55                 for(int u = pre[v]; u != v; u = pre[u]) id[u] = tn;
56                 id[v] = tn++;
57             }
58         }
59         if(tn == 0) break;
60         for(int i = 0; i != n; ++i) {
61             if(id[i] == -1) id[i] = tn++;
62         }
63         for(int i = 0; i != m; ++i) {
64             int v = edge[i].to;
65             edge[i].from = id[edge[i].from];
66             edge[i].to = id[edge[i].to];
67             if(edge[i].from != edge[i].to) edge[i].cost -= in[v];
68         }
69         n = tn;
70         root = id[root];
71     }
72     return res;
73 }
74 
75 int main() {
76     while(scanf("%d%d", &n, &m) == 2) {
77         double x[MAXN], y[MAXN];
78         for(int i = 0; i != n; ++i) scanf("%lf%lf", &x[i], &y[i]);
79         int s, e;
80         for(int i = 0; i != m; ++i) {
81             scanf("%d%d", &s, &e);
82             --s; --e;
83             edge[i].from = s;
84             edge[i].to = e;
85             edge[i].cost = sqrt((x[s]-x[e])*(x[s]-x[e])+(y[s]-y[e])*(y[s]-y[e]));
86         }
87         double ans = zhuliu(0);
88         if(ans == -1) printf("poor snoopy\n");
89         else printf("%.2lf\n", ans);
90     }
91     return 0;
92 }

 

最小树型图 [朱刘算法]

原文:https://www.cnblogs.com/pupil-xj/p/11695887.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!