ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

AcWing 野餐规划

2019-08-20 23:55:30  阅读:308  来源: 互联网

标签:num int 公园 Park fat edge 野餐 规划 AcWing


AcWing 野餐规划

Description

  • 一群小丑演员,以其出色的柔术表演,可以无限量的钻进同一辆汽车中,而闻名世界。

    现在他们想要去公园玩耍,但是他们的经费非常紧缺。

    他们将乘车前往公园,为了减少花费,他们决定选择一种合理的乘车方式,可以使得他们去往公园需要的所有汽车行驶的总公里数最少。

    为此,他们愿意通过很多人挤在同一辆车的方式,来减少汽车行驶的总花销。

    由此,他们可以很多人驾车到某一个兄弟的家里,然后所有人都钻进一辆车里,再继续前进。

    公园的停车场能停放的车的数量有限,而且因为公园有入场费,所以一旦一辆车子进入到公园内,就必须停在那里,不能再去接其他人。

    现在请你想出一种方法,可以使得他们全都到达公园的情况下,所有汽车行驶的总路程最少。

Input

  • 第一行包含整数n,表示人和人之间或人和公园之间的道路的总数量。

    接下来n行,每行包含两个字符串A、B和一个整数L,用以描述人A和人B之前存在道路,路长为L,或者描述某人和公园之间存在道路,路长为L。

    道路都是双向的,并且人数不超过20,表示人的名字的字符串长度不超过10,公园用“Park”表示。

    再接下来一行,包含整数s,表示公园的最大停车数量。

    你可以假设每个人的家都有一条通往公园的道路。

Output

  • 输出“Total miles driven: xxx”,其中xxx表示所有汽车行驶的总路程。

Sample Input

10
Alphonzo Bernardo 32
Alphonzo Park 57
Alphonzo Eduardo 43
Bernardo Park 19
Bernardo Clemenzi 82
Clemenzi Park 65
Clemenzi Herb 90
Clemenzi Eduardo 109
Park Herb 24
Herb Eduardo 79
3

Sample Output

Total miles driven: 183

题解:

  • 最小生成树,最小k度生成树。

  • 这题废话贼多,下面为翻译版本:给定一张N个点M条边的无向图,求出无向图的一棵最小生成树,满足1号节点的度数不超过给定的整数S。N <= 30。
  • 如果度数无限制直接最小生成树就行了。那么现在对1号点有了限制。那我可以先不看1号点啊,即断掉与1号点相连的所有边。这样,一张图就被分成了若干个联通块(假设为T块。那么我们贪心的想,肯定是对这若干个联通块每块做一次最小生成树。这样肯定是最优的。那么做完T后,我们再从每个联通块中选一个点到1号点权值最小的连上。这样,我们就完美的得到了一个恰好T度的最小生成树。注意,恰好T度,说明什么,如果T < S的话,我们还可以将这棵T度生成树变成一个S/S - 1/S - 2/…/T + 1度生成树,说不定会更优呢!所以这时枚举与1相连的点x,如果x到1的边不在生成树中,那么就可以得到一个赚到的价值v = 生成树中1到x路径上最大的边权 - x到1的边权。每一轮取一个最大的赚到价值,进行S - T轮后退出。或者一旦最大赚到价值 < 0了,也退出。
  • 我已经尽梨讲得明白了…
  • 写这题要有一定的码力

#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#include <algorithm>
#define N 35
#define M 100005
#define inf 0x7fffffff
using namespace std;

struct E {int next, to, dis;} e[M], edge[M];
struct Ed {int u, v, w;} ed[M];
int n = 1, m, S, T, num, num_edge, ans, tot, g;
int h[N], fat[N], head[N], Max[N];
bool vis[N], tag[N], fromOne[N];
map<string, int> mp;
map<string, bool> b;

void add(int u, int v, int w)
{
    e[++num].next = h[u];
    e[num].to = v;
    e[num].dis = w;
    h[u] = num;
}

void add_edge(int u, int v, int w)
{
    edge[++num_edge].next = head[u];
    edge[num_edge].to = v;
    edge[num_edge].dis = w;
    head[u] = num_edge;
}

bool cmp(Ed x, Ed y) {return x.w < y.w;}

void dfs(int x)
{
    vis[x] = 1, tag[x] = 1, tot++;
    for(int i = h[x]; i != 0; i = e[i].next)
        if(e[i].to != 1 && !vis[e[i].to]) dfs(e[i].to);
}

int getFat(int x)
{
    if(x == fat[x]) return x;
    return fat[x] = getFat(fat[x]);
}

void ddfs(int x, int fat)
{
    for(int i = head[x]; i != 0; i = edge[i].next)
        if(edge[i].to != fat)
        {
            Max[edge[i].to] = max(Max[x], edge[i].dis);
            ddfs(edge[i].to, x);
        }
}

void readIn()
{
    b["Park"] = 1, mp["Park"] = 1;
    for(int i = 1; i <= m; i++)
    {
        string t1, t2;
        int u, v, w;
        cin >> t1 >> t2 >> w;
        if(!b[t1]) b[t1] = 1, mp[t1] = ++n;
        if(!b[t2]) b[t2] = 1, mp[t2] = ++n;
        u = mp[t1], v = mp[t2];
        ed[i].u = u, ed[i].v = v, ed[i].w = w;
        add(u, v, w), add(v, u, w);
    }
    cin >> S;
}

int main()
{
    cin >> m;
    readIn();
    sort(ed + 1, ed + 1 + m, cmp);
    for(int i = 1; i <= n; i++) fat[i] = i;
    for(int i = 2; i <= n; i++)
        if(!vis[i])
        {
            T++, tot = g = 0;
            memset(tag, 0, sizeof(tag));
            dfs(i);
            for(int j = 1; j <= m; j++)
            {
                if(tag[ed[j].u] && tag[ed[j].v] && getFat(ed[j].u) != getFat(ed[j].v))
                {
                    fat[getFat(ed[j].u)] = getFat(ed[j].v);
                    g++, ans += ed[j].w;
                    add_edge(ed[j].u, ed[j].v, ed[j].w), add_edge(ed[j].v, ed[j].u, ed[j].w);
                }
                if(g == tot - 1) break;
            }
            int Min = inf, pos;
            for(int j = h[1]; j != 0; j = e[j].next)
                if(tag[e[j].to] && e[j].dis < Min) Min = e[j].dis, pos = e[j].to;
            ans += Min, fromOne[pos] = 1;
            add_edge(1, pos, Min), add_edge(pos, 1, Min);
        }
    Max[1] = -inf, ddfs(1, 0);
    for(int k = 1; k <= S - T; k++)
    {
        int flag = 0, cost = -inf, pos;
        for(int i = h[1]; i != 0; i = e[i].next)
            if(!fromOne[e[i].to] && cost < (Max[e[i].to] - e[i].dis) && Max[e[i].to] - e[i].dis > 0)
                cost = Max[e[i].to] - e[i].dis, pos = e[i].to, flag = 1;
        if(!flag) break;
        ans -= cost, fromOne[pos] = 1;
    }
    cout << "Total miles driven: " << ans;
    return 0;
}

标签:num,int,公园,Park,fat,edge,野餐,规划,AcWing
来源: https://www.cnblogs.com/BigYellowDog/p/11386358.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有