スパニングツリーの最小の限界(スパニングツリーにおけるKの制限)

例POJ 1639ピクニック計画


  実質的に点V0展開プロセスの最小スパニングツリーを最小全域度を求めます。

  1. まず、すべてのサブツリーのV0点を除いて最小全域木を見つけ、我々は最初の最小度スパニングツリーを決定することができるように、過去に何点、最小V0側にそれらのサブツリーのそれぞれ、および拡張によって、このことを想定していることを知っています程度がCNTです。(番号サブツリー)
  2. その後、我々は、最適な展開点を見つけ、それらのそれぞれのサブツリーのプロセスを開始、しかし、あなただけのスパニングツリーの最大のツリーに拡張ポイントのすべてのベストを知っているし、K(K - CNT)まで入れ、Aを非常に多くのポイント - ポイントは、あなたが(CNT K)を分割することができ、あります。だから、すべての時間が最も貪欲でなければなりません。
  3. どのように置き換えるには?これは、元のリンク側はオープン(それとの接合部の父親の側へのリンク、である)、最適な交換用のポイントを見つけ、その後、V0対応する点リンクを移動して行いますで、この点は、対応する最適交換ポイントを参照していません、しかし、リンクとその点V0 Vが存在し、最適点がV0パスにVの最長辺に対応する点によって置き換えられます。
  4. だから、置換値が正であれば、それはより少ないか0に等しい場合、最も貪欲の保証である、またはK点まで行われてきたことから、それは続けることができ、ループ、アルゴリズムの終了を終了します。

このプロセスをシミュレートするシミュレーションにおける推奨使用慣行、シミュレーションタイトルバーと見何のテンプレートは、ありません。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
//#include <unordered_map>
//#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 22;
int N, M, K, root[maxN], Minn_Dis[maxN], Minn_ID[maxN], ans_MST, tree_num;
int fid(int x) { return x == root[x] ? x : root[x] = fid(root[x]); }
string s1, s2;
struct Graph
{
    int u, v, w;
    Graph(int a=0, int b=0, int c=0):u(a), v(b), w(c) {}
    friend bool operator < (Graph e1, Graph e2) { return e1.w < e2.w; }
} E[maxN * maxN];
vector<Graph> vt;
map<string, int> name;
struct Build_Graph
{
    int mp[maxN][maxN]; bool link[maxN][maxN];
    inline void _add(int u, int v, int w) { link[u][v] = link[v][u] = true; mp[u][v] = mp[v][u] = min(mp[u][v], w); }
    inline void _cut(int u, int v) { link[u][v] = link[v][u] = false; mp[u][v] = mp[v][u] = INF; }
    inline void init()
    {
        for(int i=1; i<=N; i++) for(int j=1; j<=N; j++) { link[i][j] = false; mp[i][j] = INF; }
    }
} Old;
inline void Kruskal()
{
    ans_MST = tree_num = 0;
    for(int i=1, fu, fv; i<=M; i++)
    {
        if(E[i].u == 1)
        {
            fv = fid(E[i].v);
            if(Minn_Dis[fv] > E[i].w) { Minn_Dis[fv] = E[i].w; Minn_ID[fv] = E[i].v; }
            vt.push_back(Graph(E[i].u, E[i].v, E[i].w));
        }
        else if(E[i].v == 1)
        {
            fu = fid(E[i].u);
            if(Minn_Dis[fu] > E[i].w) { Minn_Dis[fu] = E[i].w; Minn_ID[fu] = E[i].u; }
            vt.push_back(Graph(E[i].v, E[i].u, E[i].w));
        }
        else
        {
            fu = fid(E[i].u); fv = fid(E[i].v);
            if(fu ^ fv)
            {
                ans_MST += E[i].w;
                root[fu] = fv;
                if(Minn_Dis[fu] < Minn_Dis[fv]) { Minn_Dis[fv] = Minn_Dis[fu]; Minn_ID[fv] = Minn_ID[fu]; }
                Old._add(E[i].u, E[i].v, E[i].w);
            }
        }
    }
    for(int i=2; i<=N; i++) if(fid(i) == i)
    {
        ans_MST += Minn_Dis[i];
        tree_num++;
        Old._add(1, Minn_ID[i], Minn_Dis[i]);
    }
}
struct DP
{
    int id, fa, dis;
    DP(int a=0, int c=0, int b=0):id(a), fa(c), dis(b) {}
    friend bool operator < (DP e1, DP e2) { return e1.dis < e2.dis; }
} dp[maxN];
void dfs(int u, int fa)
{
    for(int i=2; i<=N; i++)
    {
        if(Old.link[u][i] && (i ^ fa))
        {
            dp[i] = max(DP(i, u, Old.mp[u][i]), dp[u]);
            dfs(i, u);
        }
    }
}
void solve()
{
    int len = (int)vt.size();
    for(int tims=tree_num, maxx_det, id; tims < K; tims++)
    {
        maxx_det = -INF; id = -1;
        for(int i=0; i<len; i++)
        {
            if(dp[vt[i].v].dis - vt[i].w > maxx_det && !Old.link[1][vt[i].v])
            {
                maxx_det = dp[vt[i].v].dis - vt[i].w;
                id = i;
            }
        }
        if(maxx_det <= 0) break;
        ans_MST -= maxx_det;
        Old._add(1, vt[id].v, vt[id].w);
        Old._cut(dp[vt[id].v].id, dp[vt[id].v].fa);
        dfs(1, 0);
    }
}
inline void init()
{
    Old.init(); dp[1] = DP(1, 0, 0); vt.clear();
    for(int i=1; i<=N; i++)
    {
        root[i] = i; Minn_ID[i] = i;
        Minn_Dis[i] = INF;
    }
}
int main()
{
    scanf("%d", &M); name["Park"] = N = 1;
    for(int i=1, val; i<=M; i++)
    {
        cin >> s1 >> s2; scanf("%d", &val);
        if(!name[s1]) name[s1] = ++N;
        if(!name[s2]) name[s2] = ++N;
        E[i] = Graph(name[s1], name[s2], val);
    }
    sort(E + 1, E + M + 1);
    init();
    scanf("%d", &K);
    Kruskal();  //现在有tree_num个子树,合并,最多K个
    dfs(1, 0);
    solve();
    printf("Total miles driven: %d\n", ans_MST);
    return 0;
}

 

公開された797元の記事 ウォンの賞賛958 ・は 90000 +を見て

おすすめ

転載: blog.csdn.net/qq_41730082/article/details/104401625