[题目链接]

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. 图方法:寻找无向图联通子集的JAVA版本

    图像处理中一般使用稠密方法,即对图像进行像素集合进行处理.在图像拓扑方面,更多地应用图计算方法. 寻找无向图联通子集的JAVA版本,代码: //查找无向图的所有连通子集//wishchin!!! pu ...

  2. yar 调用rpc方法

    <?php class RpcController extends Yaf_Controller_Abstract { //RPC入口 public function indexAction($ ...

  3. Ubuntu 16.04安装和卸载软件命令

    安装软件 apt-get install softname1 softname2 softname3…… 卸载软件 apt-get remove softname1 softname2 softnam ...

  4. C#—接口和抽象类的区别?

    一.接口 接口是指对协定进行定义的引用类型,其他类型实现接口,以保证它们支持某些操作.接口指定必须由类提供的成员或实现它的其他接口.与类相似,接口可以包含方法.属性.索引器和事件作为成员. 1.接口存 ...

  5. 后台导出大量数据超时报 nginx404错误

    使用nginx服务器如果遇到timeou情况时可以如下设置参数,使用fastcgi:    fastcgi_connect_timeout 75;  链接          fastcgi_read_ ...

  6. ext4的一些特性

    delalloc介绍 delalloc是ext4下的一个新特性,延迟分配技术Delay Allocation. 实现原理为: Buffer Write时数据会被保存到page cache中,但是系统并 ...

  7. C#关键字的个人理解与注释

    C#关键字注释:abstract:抽象as:类型转换(返回转换结果)base:基类bool:布尔类型break:条件中断语句byte:字节case:条件语句catch:异常捕获后执行char:16 位 ...

  8. 如何让 Windows 上的命令行工具更好用

    侯爵老师视频详解:如何让 Windows 上的命令行工具更好用 很多 Windows 用户在打开这个小黑窗时,都会情不自禁的感慨,「实在是太丑了--」 实际上如果你用的是 Windows 8 或 Wi ...

  9. 通过PYTHON操作JIRA的COMMENT注释和TRANSITION工作流

    这是目前我们的自动化部署系统要作的,所以先实现吧. >>> from jira import JIRA >>> authed_jira = JIRA(server= ...

  10. c++ 打飞机游戏开发日志

    设计思路:控制台模式 初始化: 建立画面,初始化数据 游戏过程: 1.获取操作 2.修改数据 3.更新画面 结束: 关闭画面,delete动态分配数据 4.29日 创建游戏背景,实现飞机移动操作,实现 ...