1. 程式人生 > >Picnic Planning 【POJ - 1639】【Prime+有限度最小生成樹】

Picnic Planning 【POJ - 1639】【Prime+有限度最小生成樹】

題目連結

【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
*/