[题目链接]

http://poj.org/problem?id=1639

[算法]

首先,我们可以用深度优先遍历求出1号节点去除后有几个联通块

设共有T个联通块,若T > K则无解,否则 :

求出这些联通块的最小生成树,得到一棵最小T度生成树,我们尝试改动(K - T)条边,使得答案变得更小,具体过程如下 :

枚举所有与1相连的边,若这条边不在当前的生成树中,我们用广度优先搜索求出生成树上1号节点到该条边的节点中最长的边,用这条边的权值减去枚举边的权值即为生成树权值和变小了多少,求出这个变小的最大值

如果这个最大值大于0,将这个最大值对应的边从生成树中删除,并加入新的边,否则退出

重复以上过程(K - T)次,即可

[代码]

#include <algorithm>
#include <bitset>
#include <cctype>
#include <cerrno>
#include <clocale>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <limits>
#include <list>
#include <map>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <utility>
#include <vector>
#include <cwchar>
#include <cwctype>
#include <stack>
#include <limits.h>
using namespace std;
#define MAXN 1010
struct Edge
{
int u,v,w;
} e[MAXN],edge[MAXN][MAXN];
int i,j,n,w,k,tot,block,ans,mx;
int val[MAXN],size[MAXN],fa[MAXN],p[MAXN],belong[MAXN];
bool visited[MAXN],flag[MAXN];
int mst[MAXN][MAXN];
map<string,int> mp;
string u,v;
vector< int > a[MAXN];
pair<int,int> ps,new_e,tmp; inline bool cmp(Edge a,Edge b)
{
return a.w < b.w;
}
inline int get_root(int x)
{
if (fa[x] == x) return x;
return fa[x] = get_root(fa[x]);
}
inline void dfs(int u)
{
int i,v;
visited[u] = true;
belong[u] = block;
for (i = ; i < a[u].size(); i++)
{
v = a[u][i];
if (e[v].u == u && e[v].v != && !flag[v])
{
flag[v] = true;
edge[block][++size[block]] = e[v];
dfs(e[v].v);
} else if (e[v].v == u && e[v].u != && !flag[v])
{
flag[v] = true;
edge[block][++size[block]] = e[v];
dfs(e[v].u);
}
}
}
inline void kruskal(int id)
{
int i,su,sv;
static int s[MAXN];
for (i = ; i <= n; i++) fa[i] = i;
sort(edge[id] + ,edge[id] + size[id] + ,cmp);
for (i = ; i <= size[id]; i++)
{
su = get_root(edge[id][i].u);
sv = get_root(edge[id][i].v);
if (su != sv)
{
ans += edge[id][i].w;
mst[edge[id][i].u][edge[id][i].v] = edge[id][i].w;
mst[edge[id][i].v][edge[id][i].u] = edge[id][i].w;
fa[su] = sv;
}
}
}
inline pair<int,int> bfs(int s)
{
int i,cur,l,r,now,mx;
static bool visited[MAXN];
static pair<int,int> q[MAXN];
static int pre[MAXN];
bool found = false;
pair<int,int> res;
memset(visited,false,sizeof(visited));
q[l = r = ] = make_pair(s,);
visited[s] = true;
pre[] = -;
while (l <= r)
{
cur = q[l].first;
for (i = ; i <= n; i++)
{
if (visited[i]) continue;
if (!mst[cur][i]) continue;
visited[i] = true;
q[++r] = make_pair(i,mst[cur][i]);
pre[r] = l;
if (i == )
{
found = true;
break;
}
}
if (found) break;
l++;
}
if (!found) return make_pair(,);
now = r; mx = ;
while (pre[now] != -)
{
if (q[now].second > mx)
{
mx = q[now].second;
res = make_pair(q[pre[now]].first,q[now].first);
}
now = pre[now];
}
return res;
}
int main()
{

     cin.tie(0);
cin >> n;
mp["Park"] = ;
tot = ;
for (i = ; i <= n; i++)
{
cin >> u >> v >> w;
if (!mp[u]) mp[u] = ++tot;
if (!mp[v]) mp[v] = ++tot;
e[i] = (Edge){mp[u],mp[v],w};
a[mp[u]].push_back(i);
a[mp[v]].push_back(i);
}
scanf("%d",&k);
visited[] = true;
for (i = ; i <= n; i++)
{
if (e[i].u == && !visited[e[i].v])
{
block++;
dfs(e[i].v);
}
if (e[i].v == && !visited[e[i].u])
{
block++;
dfs(e[i].u);
}
}
if (block > k)
{
printf("-1\n");
return ;
}
for (i = ; i <= block; i++) kruskal(i);
memset(val,0x3f,sizeof(val));
for (i = ; i <= n; i++)
{
if (e[i].u == && e[i].w < val[belong[e[i].v]])
{
val[belong[e[i].v]] = e[i].w;
p[belong[e[i].v]] = e[i].v;
} else if (e[i].v == && e[i].w < val[belong[e[i].u]])
{
val[belong[e[i].u]] = e[i].w;
p[belong[e[i].u]] = e[i].u;
}
}
for (i = ; i <= block; i++)
{
ans += val[i];
mst[][p[i]] = val[i];
mst[p[i]][] = val[i];
}
for (i = ; i <= k - block; i++)
{
mx = ;
ps = new_e = make_pair(,);
for (j = ; j <= n; j++)
{
if (e[j].u == && !mst[][e[j].v])
{
tmp = bfs(e[j].v);
if (mst[tmp.first][tmp.second] - e[j].w > mx)
{
ps = tmp;
new_e = make_pair(e[j].v,e[j].w);
mx = mst[tmp.first][tmp.second] - e[j].w;
}
}
if (e[j].v == && !mst[][e[j].u])
{
tmp = bfs(e[j].u);
if (mst[tmp.first][tmp.second] - e[j].w > mx)
{
ps = tmp;
new_e = make_pair(e[j].u,e[j].w);
mx = mst[tmp.first][tmp.second] - e[j].w;
}
}
}
if (mx == ) break;
ans -= mx;
mst[][new_e.first] = new_e.second;
mst[ps.first][ps.second] = ;
}
printf("Total miles driven: %d\n",ans); return ; }

[POJ 1639] Picnic Planning的更多相关文章

  1. POJ 1639 Picnic Planning 最小k度生成树

    Picnic Planning Time Limit: 5000MS   Memory Limit: 10000K Total Submissions:11615   Accepted: 4172 D ...

  2. POJ 1639 Picnic Planning:最小度限制生成树

    题目链接:http://poj.org/problem?id=1639 题意: 给你一个无向图,n个节点,m条边,每条边有边权. 让你求一棵最小生成树,同时保证1号节点的度数<=k. 题解: 最 ...

  3. POJ 1639 Picnic Planning(最小度限制生成树)

    Description The Contortion Brothers are a famous set of circus clowns, known worldwide for their inc ...

  4. poj 1639 Picnic Planning 度限制mst

    https://vjudge.net/problem/POJ-1639 题意: 有一群人,他们要去某一个地方,每个车可以装无数个人,给出了n条路,包含的信息有路连接的地方,以及路的长度,路是双向的,但 ...

  5. poj1639,uva1537,uvalive2099,scu1622,fzu1761 Picnic Planning (最小限制生成树)

    Picnic Planning Time Limit: 5000MS   Memory Limit: 10000K Total Submissions: 10742   Accepted: 3885 ...

  6. POJ1639 - Picnic Planning

    原题链接 Description 给出一张个点的无向边权图并钦定点,求使得点的度不超过的最小生成树. Solution 首先无视掉与相连的所有边,原图会变成若干互不连通的个块.对每个块分别求MST,再 ...

  7. K度限制MST poj 1639

    /* k度限制MST:有一个点的度<=k的MST poj 1639 要求1号点的度不超过k 求MST 我们先把1号点扔掉 跑MST 假设有sum个连通分支 然后把这sum个分支连到1上 就得到了 ...

  8. 【POJ 1639】 Picnic Planning (最小k度限制生成树)

    [题意] 有n个巨人要去Park聚会.巨人A和先到巨人B那里去,然后和巨人B一起去Park.B君是个土豪,他家的停车场很大,可以停很多车,但是Park的停车场是比较小.只能停k辆车.现在问你在这个限制 ...

  9. Picnic Planning POJ - 1639(最小k度生成树)

    The Contortion Brothers are a famous set of circus clowns, known worldwide for their incredible abil ...

随机推荐

  1. Combotree--别样的构建层级json字符串

    1.先看效果 2.需要使用层级json格式,如: 3.先不要着急怎么去实现它,先来想想怎么用对象来描述它 4.代码 protected void Page_Load(object sender, Ev ...

  2. 【原创】你知道Oracle 10G能存多少数据吗

    昨天晚上在看Oracle 10G联机文档中关于bigfile tablespaces的描述(引用1),发现了关于Oracle存储极限的简单描述.bigfile tablespaces的存在,让Orac ...

  3. dubbo之泛化引用

    使用泛化调用 泛化接口调用方式主要用于客户端没有 API 接口及模型类元的情况,参数及返回值中的所有 POJO 均用 Map 表示,通常用于框架集成,比如:实现一个通用的服务测试框架,可通过 Gene ...

  4. react构建前端项目方法汇总

    react简介: 一.使用react 创建一个PC端的项目 (a):使用 yemon 创建一个 webpack 的 react 的项目 控制台安装并且产看 yemon 的版本 yo -v (b): 全 ...

  5. wx 小程序开发---开发者工具使用

    1:右侧详情界面 合法域名 都要在需要在小程序平台 配置合法域名 这样你的小程序请求的网址 才能通. 1.2如果自己的域名没有配置https 可以勾选为 不校验合法域名即可 (小程序官方规定 网址必须 ...

  6. 解析python部分常用魔术方法

    def __add__(self, *args, **kwargs): # real signature unknown """ Return self+value. & ...

  7. 【剑指Offer】29、最小的K个数

      题目描述:   输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4.   解题思路:   本题最直观的解法就是将输入的n个整数排 ...

  8. C#第五节课

    switch语句 using System;using System.Collections.Generic;using System.Linq;using System.Text;using Sys ...

  9. [51Nod 1301] 集合异或和 (dp)

    传送门 Solution 一道比较好的dp题 想了半天组合数QAQ 首先要知道的是 A<B一定是B有一位是1且A的这位是0且前面都相等 那么肯定是要枚举这一位在哪里然后求出方案数 方案数考虑类似 ...

  10. Centos 7, Torque 单节点部署

    1.准备工作 安装Torque必须首先配置linux主机名称,服务器主机名称大多默认localhost,不建议直接使用localhost. linux主机名称修改地址:http://www.cnblo ...