Picnic Planning 【POJ - 1639】【Prime+有限度最小生成樹】
阿新 • • 發佈:2018-12-25
題目連結
【Kruskal+有限度最小生成樹】另一種做法
這次換成了Prime來寫,也挺好的,充分利用下Prime的pre[]標記,就可以了。
#include <iostream> #include <cstdio> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <limits> #include <vector> #include <stack> #include <queue> #include <set> #include <map> #define lowbit(x) ( x&(-x) ) #define pi 3.141592653589793 #define e 2.718281828459045 #define INF 0x3f3f3f3f #define efs 1e-6 using namespace std; typedef unsigned long long ull; typedef long long ll; const int maxP = 30; const int maxN = 1005; int N, cnt, mp[maxP][maxP], lowercost[maxP], pre[maxP], sum, limit; string s1, s2; bool in_Tree_line[maxP][maxP], vis[maxP];; map<string, int> ns; map<string, bool> rs; struct node { int u, v, val; node(int a=0, int b=0, int c=-1):u(a), v(b), val(c) {} }dp[maxN]; void dfs(int u, int fa, int &pos, int &Minn) { for(int i=2; i<=cnt; i++) { if(in_Tree_line[u][i] && i!=fa) { if(Minn > mp[i][1]) { Minn = mp[i][1]; pos = i; } dfs(i, u, pos, Minn); } } } void Prime(int pos) { for(int i=2; i<=cnt; i++) { if(vis[pos]) continue; lowercost[i] = mp[pos][i]; pre[i] = pos; } vis[pos] = true; for(int line=1; line<=cnt-1; line++) { int minn = INF; for(int i=2; i<=cnt; i++) { if(!vis[i] && minn>lowercost[i]) { minn = lowercost[i]; pos = i; } } if(vis[pos]) break; vis[pos] = true; sum += minn; in_Tree_line[pre[pos]][pos] = in_Tree_line[pos][pre[pos]] = true; for(int i=2; i<=cnt; i++) { if(!vis[i]) { if(lowercost[i] > mp[pos][i]) { lowercost[i] = mp[pos][i]; pre[i] = pos; } } } } } void Best(int u, int fa) { for(int i=2; i<=cnt; i++) { if(i == fa || !in_Tree_line[i][u]) continue; if(dp[i].val == -1) { if(dp[u].val > mp[i][u]) dp[i] = dp[u]; else dp[i] = node(u, i, mp[i][u]); } Best(i, u); } } void solve() { int M = 0; for(int i=2; i<=cnt; i++) { if(vis[i]) continue; Prime(i); int pos = i, Minn = mp[i][1]; dfs(i, -1, pos, Minn); in_Tree_line[1][pos] = in_Tree_line[pos][1] = true; sum += Minn; M++; } for(int i=M+1; i<=limit; i++) { memset(dp, -1, sizeof(dp)); Best(1, -1); int Minn = -INF, pos = 0; for(int i=2; i<=cnt; i++) { if(!in_Tree_line[i][1] && Minn < dp[i].val - mp[i][1]) { Minn = dp[i].val - mp[i][1]; pos = i; } } if(Minn <= 0) break; sum -= Minn; in_Tree_line[pos][1] = in_Tree_line[1][pos] = true; in_Tree_line[dp[pos].u][dp[pos].v] = in_Tree_line[dp[pos].v][dp[pos].u] = false; } } void init() { ns.clear(); rs.clear(); rs["Park"] = true; ns["Park"] = 1; //定義park為"1"點 cnt = 1; sum = 0; memset(mp, INF, sizeof(mp)); memset(in_Tree_line, false, sizeof(in_Tree_line)); memset(vis, false, sizeof(vis)); } int main() { while(scanf("%d", &N)!=EOF) { init(); for(int i=1; i<=N; i++) { cin>>s1>>s2; if(!rs[s1]) ns[s1] = ++cnt; if(!rs[s2]) ns[s2] = ++cnt; rs[s1] = rs[s2] = true; int e1; scanf("%d", &e1); mp[ns[s1]][ns[s2]] = mp[ns[s2]][ns[s1]] = e1; } scanf("%d", &limit); solve(); printf("Total miles driven: %d\n", sum); } return 0; } /* 12 Park 4 84 Park 3 85 Park 6 11 Park 2 64 Park 5 57 Park 1 40 5 6 64 1 6 83 2 4 70 4 3 26 3 1 55 6 3 56 3 Accept ans = 259 */