[POJ 1639] Picnic Planning
[题目链接]
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的更多相关文章
- POJ 1639 Picnic Planning 最小k度生成树
Picnic Planning Time Limit: 5000MS Memory Limit: 10000K Total Submissions:11615 Accepted: 4172 D ...
- POJ 1639 Picnic Planning:最小度限制生成树
题目链接:http://poj.org/problem?id=1639 题意: 给你一个无向图,n个节点,m条边,每条边有边权. 让你求一棵最小生成树,同时保证1号节点的度数<=k. 题解: 最 ...
- POJ 1639 Picnic Planning(最小度限制生成树)
Description The Contortion Brothers are a famous set of circus clowns, known worldwide for their inc ...
- poj 1639 Picnic Planning 度限制mst
https://vjudge.net/problem/POJ-1639 题意: 有一群人,他们要去某一个地方,每个车可以装无数个人,给出了n条路,包含的信息有路连接的地方,以及路的长度,路是双向的,但 ...
- poj1639,uva1537,uvalive2099,scu1622,fzu1761 Picnic Planning (最小限制生成树)
Picnic Planning Time Limit: 5000MS Memory Limit: 10000K Total Submissions: 10742 Accepted: 3885 ...
- POJ1639 - Picnic Planning
原题链接 Description 给出一张个点的无向边权图并钦定点,求使得点的度不超过的最小生成树. Solution 首先无视掉与相连的所有边,原图会变成若干互不连通的个块.对每个块分别求MST,再 ...
- K度限制MST poj 1639
/* k度限制MST:有一个点的度<=k的MST poj 1639 要求1号点的度不超过k 求MST 我们先把1号点扔掉 跑MST 假设有sum个连通分支 然后把这sum个分支连到1上 就得到了 ...
- 【POJ 1639】 Picnic Planning (最小k度限制生成树)
[题意] 有n个巨人要去Park聚会.巨人A和先到巨人B那里去,然后和巨人B一起去Park.B君是个土豪,他家的停车场很大,可以停很多车,但是Park的停车场是比较小.只能停k辆车.现在问你在这个限制 ...
- Picnic Planning POJ - 1639(最小k度生成树)
The Contortion Brothers are a famous set of circus clowns, known worldwide for their incredible abil ...
随机推荐
- 图方法:寻找无向图联通子集的JAVA版本
图像处理中一般使用稠密方法,即对图像进行像素集合进行处理.在图像拓扑方面,更多地应用图计算方法. 寻找无向图联通子集的JAVA版本,代码: //查找无向图的所有连通子集//wishchin!!! pu ...
- yar 调用rpc方法
<?php class RpcController extends Yaf_Controller_Abstract { //RPC入口 public function indexAction($ ...
- Ubuntu 16.04安装和卸载软件命令
安装软件 apt-get install softname1 softname2 softname3…… 卸载软件 apt-get remove softname1 softname2 softnam ...
- C#—接口和抽象类的区别?
一.接口 接口是指对协定进行定义的引用类型,其他类型实现接口,以保证它们支持某些操作.接口指定必须由类提供的成员或实现它的其他接口.与类相似,接口可以包含方法.属性.索引器和事件作为成员. 1.接口存 ...
- 后台导出大量数据超时报 nginx404错误
使用nginx服务器如果遇到timeou情况时可以如下设置参数,使用fastcgi: fastcgi_connect_timeout 75; 链接 fastcgi_read_ ...
- ext4的一些特性
delalloc介绍 delalloc是ext4下的一个新特性,延迟分配技术Delay Allocation. 实现原理为: Buffer Write时数据会被保存到page cache中,但是系统并 ...
- C#关键字的个人理解与注释
C#关键字注释:abstract:抽象as:类型转换(返回转换结果)base:基类bool:布尔类型break:条件中断语句byte:字节case:条件语句catch:异常捕获后执行char:16 位 ...
- 如何让 Windows 上的命令行工具更好用
侯爵老师视频详解:如何让 Windows 上的命令行工具更好用 很多 Windows 用户在打开这个小黑窗时,都会情不自禁的感慨,「实在是太丑了--」 实际上如果你用的是 Windows 8 或 Wi ...
- 通过PYTHON操作JIRA的COMMENT注释和TRANSITION工作流
这是目前我们的自动化部署系统要作的,所以先实现吧. >>> from jira import JIRA >>> authed_jira = JIRA(server= ...
- c++ 打飞机游戏开发日志
设计思路:控制台模式 初始化: 建立画面,初始化数据 游戏过程: 1.获取操作 2.修改数据 3.更新画面 结束: 关闭画面,delete动态分配数据 4.29日 创建游戏背景,实现飞机移动操作,实现 ...