最小树型图 [朱刘算法](定根/不定根/森林)

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

// 例题 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
");
89         else printf("%.2lf
", ans);
90     }
91     return 0;
92 }

// hdu 2121 (不定跟)

思路: 虚拟源点

  1 /*
  2  * @Promlem: 
  3  * @Time Limit: ms
  4  * @Memory Limit: k
  5  * @Author: pupil-XJ
  6  * @Date: 2019-10-18 19:02:26
  7  * @LastEditTime: 2019-10-19 01:13:33
  8  */
  9 #include<cstdio>
 10 #include<cstring>
 11 #include<cmath>
 12 #include<iostream>
 13 #include<string>
 14 #include<algorithm>
 15 #include<vector>
 16 #include<queue>
 17 #include<stack>
 18 #include<set>
 19 #include<map>
 20 #define rep(i, n) for(int i=0;i!=n;++i)
 21 #define per(i, n) for(int i=n-1;i>=0;--i)
 22 #define Rep(i, sta, n) for(int i=sta;i!=n;++i)
 23 #define rep1(i, n) for(int i=1;i<=n;++i)
 24 #define per1(i, n) for(int i=n;i>=1;--i)
 25 #define Rep1(i, sta, n) for(int i=sta;i<=n;++i)
 26 #define L k<<1
 27 #define R k<<1|1
 28 #define mid (tree[k].l+tree[k].r)>>1
 29 using namespace std;
 30 const int INF = 0x3f3f3f3f;
 31 typedef long long ll;
 32 const int MAXN = 1000+5;
 33 const int MAXM = 10000+5;
 34 
 35 struct node {
 36     int from, to, w;
 37 } edge[MAXM+MAXN];
 38 
 39 int pos;
 40 int pre[MAXN], vis[MAXN], id[MAXN], in[MAXN];
 41 
 42 ll zhuliu(int n, int m) {
 43     int root = 0;
 44     ll ans = 0;
 45     while(1) {
 46         rep(i, n) in[i] = INF;
 47         rep(i, m) {
 48             int u = edge[i].from, v = edge[i].to;
 49             if(u != v && edge[i].w < in[v]) {
 50                 pre[v] = u;
 51                 in[v] = edge[i].w;
 52                 if(u == root) pos = i;
 53             }
 54         }
 55         rep(i, n) {
 56             if(i != root && in[i] == INF) return -1;
 57         }
 58         int tn = 0;
 59         in[root] = 0;
 60         rep(i, n) id[i] = vis[i] = -1;
 61         rep(i, n) {
 62             ans += in[i];
 63             int v = i;
 64             while(vis[v] != i && id[v] == -1 && v != root) {
 65                 vis[v] = i;
 66                 v = pre[v];
 67             }
 68             if(v != root && id[v] == -1) {
 69                 for(int u = pre[v]; u != v; u = pre[u]) id[u] = tn;
 70                 id[v] = tn++;
 71             }
 72         }
 73         if(tn == 0) break;
 74         rep(i, n) if(id[i] == -1) id[i] = tn++;
 75         rep(i, m) {
 76             int v = edge[i].to;
 77             edge[i].from = id[edge[i].from];
 78             edge[i].to = id[edge[i].to];
 79             if(edge[i].from != edge[i].to) edge[i].w -= in[v];
 80         }
 81         root = id[root];
 82         n = tn;
 83     }
 84     return ans;
 85 }
 86 
 87 int main() {
 88     ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
 89     int n, m, sum;
 90     while(cin >> n >> m) {
 91         int s, e;
 92         sum = 0;
 93         rep(i, m) {
 94             cin >> edge[i].from >> edge[i].to >> edge[i].w;
 95             ++edge[i].from; ++edge[i].to;
 96             sum += edge[i].w;
 97         }
 98         ++sum;
 99         Rep(i, m, n+m) {
100             edge[i].from = 0; edge[i].to = i - m + 1;
101             edge[i].w = sum;
102         }
103         ll ans = zhuliu(n+1, n+m);
104         if(ans == -1 || ans-sum >= sum) cout << "impossible" << "

";
105         else cout << ans-sum << " " << pos-m << "

";
106     }
107     return 0;
108 }

 // hdu 4009 (生成森林)

  1 /*
  2  * @Promlem: 
  3  * @Time Limit: ms
  4  * @Memory Limit: k
  5  * @Author: pupil-XJ
  6  * @Date: 2019-10-19 16:21:30
  7  * @LastEditTime: 2019-10-19 17:28:08
  8  */
  9 #include<cstdio>
 10 #include<cstring>
 11 #include<cmath>
 12 #include<iostream>
 13 #include<string>
 14 #include<algorithm>
 15 #include<vector>
 16 #include<queue>
 17 #include<stack>
 18 #include<set>
 19 #include<map>
 20 #define rep(i, n) for(int i=0;i!=n;++i)
 21 #define per(i, n) for(int i=n-1;i>=0;--i)
 22 #define Rep(i, sta, n) for(int i=sta;i!=n;++i)
 23 #define rep1(i, n) for(int i=1;i<=n;++i)
 24 #define per1(i, n) for(int i=n;i>=1;--i)
 25 #define Rep1(i, sta, n) for(int i=sta;i<=n;++i)
 26 #define L k<<1
 27 #define R k<<1|1
 28 #define mid (tree[k].l+tree[k].r)>>1
 29 using namespace std;
 30 const int INF = 0x3f3f3f3f;
 31 typedef long long ll;
 32 const int MAXN = 1000+5;
 33 const int MAXM = MAXN*MAXN+MAXN;
 34 
 35 struct node {
 36     int from, to, w;
 37 } edge[MAXM];
 38 
 39 int X, Y, Z;
 40 int x[MAXN], y[MAXN], z[MAXN];
 41 
 42 int pre[MAXN], vis[MAXN], id[MAXN], in[MAXN];
 43 
 44 int zhuliu(int n, int m) {
 45     int root = 0;
 46     int sum = 0;
 47     while(1) {
 48         rep(i, n) in[i] = INF;
 49         rep(i, m) {
 50             int u = edge[i].from, v = edge[i].to;
 51             if(u != v && edge[i].w < in[v]) {
 52                 pre[v] = u;
 53                 in[v] = edge[i].w;
 54             }
 55         }
 56         rep(i, n) if(i != root && in[i] == INF) return -1;
 57         int tn = 0;
 58         in[root] = 0;
 59         rep(i, n) vis[i] = id[i] = -1;
 60         rep(i, n) {
 61             sum += in[i];
 62             int v = i;
 63             while(vis[v] != i && id[v] == -1 && v != root) {
 64                 vis[v] = i;
 65                 v = pre[v];
 66             }
 67             if(v != root && id[v] == -1) {
 68                 for(int u = pre[v]; u != v; u = pre[u]) id[u] = tn;
 69                 id[v] = tn++;
 70             }
 71         }
 72         if(tn == 0) break;
 73         rep(i, n) if(id[i] == -1) id[i] = tn++;
 74         rep(i, m) {
 75             int v = edge[i].to;
 76             edge[i].from = id[edge[i].from];
 77             edge[i].to = id[edge[i].to];
 78             if(edge[i].from != edge[i].to) edge[i].w -= in[v];
 79         }
 80         root = id[root];
 81         n = tn;
 82     }
 83     return sum;
 84 }
 85 
 86 int main() {
 87     //ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
 88     int n, m;
 89     while(scanf("%d%d%d%d", &n, &X, &Y, &Z) == 4 && n) { //cin >> n >> X >> Y >> Z
 90         m = 0;
 91         rep1(i, n) scanf("%d%d%d", &x[i], &y[i], &z[i]); //cin >> x[i] >> y[i] >> z[i];
 92         int c, v, sum;
 93         rep1(u, n) {
 94             scanf("%d", &c); //cin >> c;
 95             rep(j, c) {
 96                 scanf("%d", &v); //cin >> v;
 97                 if(u != v) {
 98                     sum = (abs(x[u]-x[v])+abs(y[u]-y[v])+abs(z[u]-z[v]))*Y;
 99                     if(z[v] > z[u]) sum += Z;
100                     edge[m].from = u; edge[m].to = v;
101                     edge[m].w = sum;
102                     ++m;
103                 }
104             }
105         }
106         Rep(i, m, m+n) {
107             edge[i].from = 0; edge[i].to = i - m + 1;
108             edge[i].w = z[i-m+1]*X;
109         }
110         int ans = zhuliu(n+1, n+m);
111         printf("%d
", ans); //cout << ans << "
";
112     }
113     return 0;
114 }
原文地址:https://www.cnblogs.com/pupil-xj/p/11695887.html