[题目链接]

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. 酷派改变者S1(C105/C105-6/C105-8) 解锁BootLoader 并刷入recovery root

    首先下载好工具链接:https://pan.baidu.com/s/1qZjOCUw 密码:u2dr 备用下载链接:https://pan.baidu.com/s/1pMlmAef 本篇教程教你如何傻 ...

  2. wamp中的mysql服务与原来安装的mysql服务冲突的解决办法

    如果原来机器上已经安装了mysql,在安装wamp之后,打开wamp上的mysql时会打不开,或者会将原来安装的mysql服务关闭.原因是两个mysql共用了3306端口,解决办法是更改其中的一个端口 ...

  3. Shiny学习实践01

    Shiny是什么东东? 官方描述: Shiny is an R package that makes it easy to build interactive web apps straight fr ...

  4. 两款工作流JBPM和CCBPM的对比

    以国外流行的工作流jbpm4的模式与当今中国开源的ccbpm(ccflow和jflow的总称)流程引擎对照.以便让各位能够了解到中国国情的工作流引擎与国际流行的设计规则的差别.不同.与优缺点. 国外工 ...

  5. 安卓JNI使用OpenCV

    OpenCV也有Java数据结构的包,不过计算速度还是很慢,非不得已不使用此种方式调用OpenCV.使用NDK编写底层OpenCv的调用代码,使用JNI对代码进行封装,可以稍微提高一点效率. 参考链接 ...

  6. java 发送http请求

    参考别人的 package test; import java.io.BufferedReader; import java.io.IOException; import java.io.InputS ...

  7. react获取url查询参数

    继承自React.Component的this.props.location.query对象下有当前url的各种查询参数.简单的例子:在控制台打印这个对象 import React from 'rea ...

  8. tomcat配置SSH加密

    [root@tomcat2 ~]# keytool -genkeypair -alias tomcat -keyalg RSA -keystore /usr/local/tomcat7/keystor ...

  9. 【转载】jmeter将上一个接口返回值作为下一个接口的请求参数

    第一:通过JSON Extractor 插件来提取JSON响应结果 原文地址:http://blog.csdn.net/dreamtl/article/details/68957122 接口响应结果, ...

  10. [置顶] Java Web学习总结(24)——SSM(Spring+SpringMVC+MyBatis)框架快速整合入门教程

    1.基本概念 1.1.Spring Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One  ...