https://vjudge.net/problem/POJ-1639

题意:

有一群人,他们要去某一个地方,每个车可以装无数个人,给出了n条路,包含的信息有路连接的地方,以及路的长度,路是双向的,但是终点只有一个,并且终点能停的车的数量是有限制的,问最少走的路是多少。

思路:

因为终点的停车的数量是有限制的,所以终点的度是有限制的,又因为这题可以用最小生成树解决,所以就是度限制最小生成树。

度限制最小生成树求解思想并不复杂,首先我们把有度限制的点给忽略,然后给每一个连通分量求最小生成树,最后把每一个连通分量中与有度限制的点的距离最小的点与度限制点连接,假设有m个连通分量。

那么我们现在求出了m限制的最小生成树,假如限制数k < m,那么就无解。

当k >= m时,我们可以在m度限制mst的基础上,求m + 1,m + 2。。。k度限制最小生成树,求法也不是很难懂,但是程序就很难写了Orz。

如何求呢?枚举每一条未在生成树中与(现在我们把度限制点叫做R点)R点相连的边,然后把边加入生成树,必然会形成环,然后把环中与R点不相连的权值最大的边去掉,枚举之后的最小值就是m+1度限制最小生成树的值。然后依次求到k限制mst,求其中的最小值。

但是,依次枚举的话时间复杂度非常高,所以我们要优化。这时就用到了动态规划的思想。将与R点到其它点的边权值最大求出,之后加边的时候,直接替换就可以了。

转移方程 dp[v] = max(dp[father(v)],w(v , father(v)));

看不懂就多看几遍Orrrrrrrrrrrrrrrrrrrrrrrrz。

代码:

 #include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string.h>
#include <map>
#include <string>
using namespace std; const int inf = 0x3f3f3f3f; struct edge
{
int x,y;
int v;
} a[],dp[]; map<string,int> mmp;
bool flag[][];
int par[];
int g[][]; int ans;
int num;
int du,lim; int fin(int x)
{
if (x == par[x]) return x;
else return par[x] = fin(par[x]);
} void unit(int x,int y)
{
x = fin(x);
y = fin(y); if (x == y) return; par[x] = y;
} void dfs(int cur,int pre)
{
for (int i = ;i <= num;i++)
{
if (i != pre && flag[cur][i])
{
if (dp[i].v == -)
{
if (dp[cur].v > g[cur][i])
{
dp[i] = dp[cur];
}
else
{
dp[i].x = cur;
dp[i].y = i;
dp[i].v = g[cur][i];
}
} dfs(i,cur);
}
}
} void solve(void)
{
for (int i = du + ;i <= lim;i++)
{
memset(dp,-,sizeof(dp)); dp[].v = -inf; for (int j = ;j <= num;j++)
if (flag[j][]) dp[j].v = -inf; dfs(,-); int mi = inf,tmp; for (int j = ;j <= num;j++)
{
if (g[][j] != -)
{
if (mi > g[][j] - dp[j].v)
{
mi = g[][j] - dp[j].v;
tmp = j;
}
}
} if (mi >= ) break; ans += mi; int x = dp[tmp].x,y = dp[tmp].y; flag[x][y] = flag[y][x] = ; flag[][tmp] = flag[tmp][] = ;
}
} int get_num(string aa)
{
if (mmp[aa]) return mmp[aa];
else
{
mmp[aa] = ++num;
return num;
}
} bool cmp(edge aa,edge bb)
{
return aa.v < bb.v;
} int main()
{
num = ; mmp["Park"] = ; memset(g,-,sizeof(g)); int n; scanf("%d",&n); for (int i = ;i < n;i++)
{
string aa,bb;
int v; cin >> aa >> bb; scanf("%d",&v); int x = get_num(aa),y = get_num(bb); if (g[x][y] == -) g[x][y] = g[y][x] = v;
else g[x][y] = g[y][x] = min(v,g[x][y]); a[i].x = x;
a[i].y = y;
a[i].v = g[x][y];
} for (int i = ;i <= num;i++) par[i] = i; scanf("%d",&lim); sort(a,a+n,cmp); for (int i = ;i < n;i++)
{
int x = a[i].x,y = a[i].y; if (x == || y == ) continue;
if (fin(x) == fin(y)) continue; ans += a[i].v; unit(x,y); flag[x][y] = flag[y][x] =;
} int minn[],tmp[]; memset(minn,inf,sizeof(minn)); for (int i = ;i <= num;i++)
{
int rt = fin(i); if (g[][i] != -)
{
if (g[][i] < minn[rt])
{
minn[rt] = g[][i];
tmp[rt] = i;
}
}
} for (int i = ;i <= num;i++)
{
if (minn[i] != inf)
{
du++;
flag[][tmp[i]] = flag[tmp[i]][] = ;
ans += minn[i];
}
} solve(); printf("Total miles driven: %d\n",ans); return ;
}

poj 1639 Picnic Planning 度限制mst的更多相关文章

  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

    [题目链接] http://poj.org/problem?id=1639 [算法] 首先,我们可以用深度优先遍历求出1号节点去除后有几个联通块 设共有T个联通块,若T > K则无解,否则 : ...

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

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

  5. poj 1639 最小k度限制生成树

    题目链接:https://vjudge.net/problem 题意: 给各位看一下题意,算法详解看下面大佬博客吧,写的很好. 参考博客:最小k度限制生成树 - chty - 博客园  https:/ ...

  6. K度限制MST poj 1639

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

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

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

  8. POJ1639 - Picnic Planning

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

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

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

随机推荐

  1. AVL树(Java实现)

    AVL树基本介绍 AVL树是一种自平衡的二叉查找树,在AVL树中任何节点的两个子树的高度差不能超过1.就是相当于在二叉搜索树的基础上,在插入和删除时进行了平衡处理. 不平衡的四种情况 LL:结构介绍 ...

  2. Java生成图片验证码

    在日常我们在登录或者注册的时候,网页上会出现验证码让我们填写,其实利用jdk提供给我们的工具类完全可以模拟出来一个生成验证码图片的功能. package util; import javax.imag ...

  3. Mysql语句的执行过程

    当你希望MySQL能够以更高的性能运行查询时,最好的办法是弄清楚MySQL是如何优化和执行查询.<高性能MySQL> MySQL客户端与服务器端的通信特点 客户端与服务器之间是半双工通信, ...

  4. c++ --> const关键字总结

    const关键字总结 C++中的const关键字的用法非常灵活,而使用const将大大改善程序的健壮性.const 是C++中常用的类型修饰符,常类型是指使用类型修饰符const说明的类型,常类型的变 ...

  5. Java几种建立实例的方法

    1.new something obj=new something();   2.clone 根据现有的对象实例来建立里一个新对象实例. 只限于实现了java.lang.Cloneable接口的类.否 ...

  6. Android 源代码结构

    简介 在使用Andriod SDK进行应用程序开发的时候,我们需要对源代码进行调试,有可能需要进入到某个Android API函数内部进行跟踪调试.但是,如果目标版本的SDK没有关联对应版本的源代码的 ...

  7. C#中的String类

    一.String类的方法 1. Trim():清除字符串两端的空格 2. ToLower():将字符串转换为小写 3. Equals():比较两个字符串的值,bool 4. IndexOf(value ...

  8. 『备注』&#x; 格式 的编码转换

    在很多 网站(或者很多 WebService), 我们总能看到 Ӓ &#A22A;  这种格式 的编码. 如何将这种编码 转换成 实际文本,C#代码如下: //各种 幺蛾子网页图标 请参见: ...

  9. SpagoBi开发示例——员工离职人数统计

    1.开发工具:SpagoBIStudio_5.1,操作界面和使用方法和eclipse没差 安装参考:http://www.cnblogs.com/starlet/p/4778334.html   2. ...

  10. Rails Migration Data Model栏位修改及数据类型介绍

    测试版本Ruby:2.3.1   Rails:5.0.1 一.增加栏位       给devise默认的用户新增增加username字段 $ rails generate migration add_ ...