度限制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\n", ans); 219 //cout << "Total miles driven: " << ans << endl; 220 return 0; 221 }