版权声明:https://blog.csdn.net/qq_41730082 https://blog.csdn.net/qq_41730082/article/details/85199197
题目链接
【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
*/