度限制MST

POJ1639 顶点度数限制的最小生成树

做法:首先把和顶点相连的X条边全部删掉 得到顶点和 X个连通块

然后求出这X个连通块的MST 再把X条边连接回去这样我们就首先求出了X度MST

知道了X度MST 我们接下来要求X+1度MST 也就是再给顶点一条边 但是加上了这条边就会生成一个环

我们需要删掉这个环上最大权值的边

所有我们每次从N度向N+1度推进的时候需要O(N)DP求出并记录顶点到其他点的权值最大边

然后我们枚举还没有连上的边 如果删掉的边不会比加入的边大的话 就不继续推进了(剪枝)

  1 /*Huyyt*/
  2 //#include<bits/stdc++.h>
  3 #include<iostream>
  4 #include<cstdio>
  5 #include<cstdlib>
  6 #include<cstring>
  7 #include<cmath>
  8 #include<stdio.h>
  9 #include<string.h>
 10 #include<algorithm>
 11 #include<map>
 12 #include<set>
 13 #include<vector>
 14 #define mem(a,b) memset(a,b,sizeof(a))
 15 #define pb push_back
 16 using namespace std;
 17 typedef long long ll;
 18 typedef unsigned long long ull;
 19 const int mod = 1e9 + 7;
 20 const int gakki = 5 + 2 + 1 + 19880611 + 1e9;
 21 const int MAXN = 1e2 + 5, MAXM = 2e4 + 5;
 22 /*int to[MAXM << 1], nxt[MAXM << 1], Head[MAXN], ed = 1;
 23 int cost[MAXM << 1];
 24 inline void addedge(int u, int v, int c)
 25 {
 26         to[++ed] = v;
 27         nxt[ed] = Head[u];
 28         cost[ed] = c;
 29         Head[u] = ed;
 30 }*/
 31 int dis[250][250];
 32 int par[250];
 33 map<string, int> mp;
 34 string mpu, mpv;
 35 bool connect[250];
 36 int n, K;
 37 int cnt = 1, root, costnow, ans = 0, ccnt = 0;
 38 int dp[250];
 39 struct node
 40 {
 41         int u, v, c;
 42 } edge[405], cmin[405], rootedge[405], cur, choose[405];
 43 bool cmp(node a, node b)
 44 {
 45         return a.c < b.c;
 46 }
 47 int findpar(int x)
 48 {
 49         return par[x] == x ? x : par[x] = findpar(par[x]);
 50 }
 51 void init()
 52 {
 53         for (int i = 1; i <= n; i++)
 54         {
 55                 dp[i] = -1;
 56                 choose[i].c = -1;
 57         }
 58 }
 59 void dfs(int x, int pre)
 60 {
 61         node better;
 62         for (int v = 2; v <= n; v++)
 63         {
 64                 if (v != pre && (dis[x][v] != 1000000000))
 65                 {
 66                         if (dis[x][v] > choose[x].c)
 67                         {
 68                                 choose[v].u = x, choose[v].v = v, choose[v].c = dis[x][v];
 69                                 dp[v] = dis[x][v];
 70                         }
 71                         else
 72                         {
 73                                 choose[v] = choose[x];
 74                                 dp[v] = dp[x];
 75                         }
 76                         dfs(v, x);
 77                 }
 78         }
 79 }
 80 int main()
 81 {
 82         scanf("%d", &n);
 83         for (int i = 1; i <= n + 1; i++)
 84         {
 85                 par[i] = i;
 86                 cmin[i].c = 1000000000;
 87                 for (int j = 1; j <= n + 1; j++)
 88                 {
 89                         dis[i][j] = 1000000000;
 90                 }
 91         }
 92         mp["Park"] = 1;
 93         for (int i = 1; i <= n; i++)
 94         {
 95                 cin >> mpu >> mpv >> costnow;
 96                 if (!mp[mpu])
 97                 {
 98                         mp[mpu] = ++cnt;
 99                 }
100                 if (!mp[mpv])
101                 {
102                         mp[mpv] = ++cnt;
103                 }
104                 edge[i].u = mp[mpu], edge[i].v = mp[mpv];
105                 edge[i].c = costnow;
106                 //cout << edge[i].u << "  " << edge[i].v << "  " << costnow << endl;
107                 if (edge[i].u == 1 || edge[i].v == 1)
108                 {
109                         rootedge[++ccnt] = edge[i];
110                 }
111         }
112         scanf("%d", &K);
113         sort(edge + 1, edge + 1 + n, cmp);
114         for (int i = 1; i <= n; i++)
115         {
116                 int u1, v1;
117                 u1 = edge[i].u, v1 = edge[i].v;
118                 if (u1 != 1 && v1 != 1)
119                 {
120                         int fx = findpar(u1), fy = findpar(v1);
121                         if (fx != fy)
122                         {
123                                 par[fx] = fy;
124                                 dis[u1][v1] = dis[v1][u1] = edge[i].c;
125                                 ans += edge[i].c;
126                                 //cout << " u " << u1 << " v " << v1 << "   " << ans << endl;
127                         }
128                 }
129         }
130         for (int i = 1; i <= ccnt; i++)
131         {
132                 int u1, v1;
133                 u1 = rootedge[i].u, v1 = rootedge[i].v;
134                 if (u1 != 1)
135                 {
136                         int fx = findpar(u1);
137                         if (cmin[fx].c > rootedge[i].c)
138                         {
139                                 cmin[fx] = rootedge[i];
140                         }
141                 }
142                 else
143                 {
144                         int fx = findpar(v1);
145                         if (cmin[fx].c > rootedge[i].c)
146                         {
147                                 cmin[fx] = rootedge[i];
148                         }
149                 }
150         }
151         int m = 0;
152         for (int i = 2; i <= cnt; i++)
153         {
154                 int fx = findpar(i);
155                 if (!connect[fx])
156                 {
157                         m++;
158                         connect[fx] = true;
159                         cur = cmin[fx];
160                         dis[cur.u][cur.v] = dis[cur.v][cur.u] = cur.c;
161                         ans += cur.c;
162                         //cout << " i " << i <<  " u " << cur.u << " v " << cur.v << "   " << ans << endl;
163                         for (int j = 1; j <= ccnt; j++)
164                         {
165                                 if (rootedge[j].u == cur.u && rootedge[j].v == cur.v)
166                                 {
167                                         rootedge[j].c = -1;
168                                         break;
169                                 }
170                         }
171                 }
172         }
173         for (int i = m + 1; i <= K; i++)
174         {
175                 init();
176                 dfs(1, -1);
177                 int ansmanx = 0;
178                 node best;
179                 int want;
180                 int where;
181                 for (int j = 1; j <= ccnt; j++)
182                 {
183                         if (rootedge[j].c != -1)
184                         {
185                                 int u1, v1;
186                                 u1 = rootedge[j].u, v1 = rootedge[j].v;
187                                 if (u1 != 1)
188                                 {
189                                         if (dp[u1] - rootedge[j].c > ansmanx)
190                                         {
191                                                 where = j;
192                                                 best = rootedge[j];
193                                                 want = u1;
194                                                 ansmanx = dp[u1] - rootedge[j].c;
195                                         }
196                                 }
197                                 else
198                                 {
199                                         if (dp[v1] - rootedge[j].c > ansmanx)
200                                         {
201                                                 where = j;
202                                                 best = rootedge[j];
203                                                 want = v1;
204                                                 ansmanx = dp[v1] - rootedge[j].c;
205                                         }
206                                 }
207                         }
208                 }
209                 if (ansmanx == 0)
210                 {
211                         break;
212                 }
213                 dis[best.u][best.v] = dis[best.v][best.u] = best.c;
214                 dis[choose[want].u][choose[want].v] = dis[choose[want].v][choose[want].u] = 1000000000;
215                 rootedge[where].c = -1;
216                 ans -= ansmanx;
217         }
218         printf("Total miles driven: %d
", ans);
219         //cout << "Total miles driven: " << ans << endl;
220         return 0;
221 }
//度生成树
原文地址:https://www.cnblogs.com/Aragaki/p/9496022.html