ACdream 1083 有向无环图dp
题目链接:点击打开链接
人民城管爱人民
Problem Description
一天GG正在和他的后宫之中的一个的MM在外面溜达,MM突然说了一句,“我想吃鸡蛋灌饼”……当他们吃的正high的时候。城管出现了!作为传说中的最强军事力量,卖鸡蛋灌饼的小贩在他们面前也仅仅算是战力为的5的渣滓,一秒钟就被秒杀了……
在这场屠杀中。GG和他的后宫本来仅仅是围观群众,可是不幸的是,城管看到了GG胃里的鸡蛋灌饼。他们要逮捕GG!可是GG显然不能让他们如愿,于是GG带着后宫開始了往大运村的逃亡之旅。
整个地图有n个路口。灌饼摊在0号路口。大运村在n-1号路口。有m条仅仅能单向通过的道路连接这n个路口,每条道路用一个正整数表示走过须要的时间。整个地图没有环路,但两个路口之间可能有多条通路。
如今GG希望以最短的时间到大运村,但不幸的是。城管为了抓住他动用了卫星对他进行空中跟踪,并且会在某一时刻空降到某一条道路上进行封锁(封锁会在瞬间完毕。可惜动静太大了GG也能在第一时间知道哪条道路被封锁了),之后这条路就无法通过了。
在整个行动中仅仅会出现一次空降。并且不会在GG经过这条道路的时候进行封锁,也就是说,不会在GG在某条路上走了一半的时候封锁这条路。并且,城管们希望尽可能的延缓GG到达大运村的时间。
如今GG希望知道。自己多久能到达大运村。方便安排之后和其它后宫的约会。
注意两方是以博弈的思想来进行选择。即GG希望时间最短,城管希望时间最长。并且他们都很聪明会做出最佳的选择。
Input
输入第一行为数据组数T(T<=30)。
每组数据第一行包括两个整数n,m(2<=n<=10000,1<=m<=100000),表示路口数和道路数。
之后m行描写叙述了全部的道路,每行有三个整数u,v,w(0<=u,v<n。0<w<=1000),表示路口u到路口v有一条须要w时间走过的道路。
Output
Sample Input
2
5 6
0 1 1
1 2 1
2 4 1
1 4 3
0 3 2
3 4 1
3 4
0 1 1
0 1 2
1 2 3
1 2 4
Sample Output
4
5
Source
思路:
1、首先这个dp一定是逆向拓扑序(把全部边反向进行拓扑排序),这样我们在计算u点时,通过有向边(u->v)把u点的状态从v点转移过来。能保证v点一定是已计算过的
2、用dis[i]表示i点到终点的最短路。dp[i]表示i点到终点的删边最短路(这里所谓的删边。删除的边是在i-终点的路径上)
3、那么我们设GG站在u点,通过u->v的边把状态从v转移过来。
4、计算dis[u]比較easy,就是min(dis[v]+edge[i].dis)
5、计算dp[u]:依据定义dp[u] 是删边最短路,则删除的边是在u-终点的路径上,那么显然有2种情况
1)删除u-v这样的与u相连的边
2)删除v-终点上的边
对于2):那么GG有主动权,显然是选择edge[i].dis + dp[v] 中最小的(我们设这个最小值为smin)
对于1):军队拥有主动权,军队一定选择删掉一条边,那么删完以后GG自然还是选择走最短路,也就是GG仅仅能选择edge[i].dis+dis[v] 中次小值(设这个值为dmin
这里注意的是。军队拥有的主动权是能够随意选择一条边,所以dp[u]=max(dmin, smin)
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<set>
#include<queue>
#include<math.h>
#include<map>
using namespace std;
#define N 10050
#define M 100500
#define inf 10000000
struct Edge{
int from, to, dis, nex;
}edge[M<<1];
int head[N], edgenum;
void add(int u, int v, int d){
Edge E={u,v,d,head[u]};
edge[edgenum] = E;
head[u] = edgenum++;
} int n,m;
int sp[N], in[N];
void topsort(){//把图进行拓扑序
queue<int>q;
for(int i = 0; i < n; i++)if(in[i]==0)q.push(i);
int top = 0;
while(!q.empty()){
int u = q.front(); q.pop();
sp[top++] = u;
for(int i = head[u]; ~i; i = edge[i].nex)if(i&1){
int v = edge[i].to;
in[v]--;
if(!in[v])q.push(v);
}
}
}
int dp[N][2], a[M];//dp[u][0]表示1到u的最短路 dp[u][1]表示1到u的次小最短路
void work(int u){
if(u == n-1){ dp[u][0] = dp[u][1] = 0; return ; }
int top = 0, smin = inf;
for(int i = head[u]; ~i; i = edge[i].nex)if(!(i&1)){
int v = edge[i].to;
dp[u][0] = min(dp[u][0], dp[v][0]+edge[i].dis);
smin = min(smin, dp[v][1]+edge[i].dis);
a[top++] = dp[v][0] + edge[i].dis;
}
if(top<2){dp[u][1] = inf; return ;}
int fir = a[0], sec = a[1];
if(fir>sec)swap(fir,sec);
for(int i = 2; i < top; i++){
if(a[i]<=fir)
sec = fir, fir = a[i];
else sec = min(sec, a[i]);
}
dp[u][1] = max(smin, sec);
}
void init(){memset(head, -1, sizeof head);edgenum = 0;}
int main(){
int T, i, j, u, v, d;scanf("%d",&T);
while(T--){
init();
memset(in, 0, sizeof in);
scanf("%d %d",&n,&m);
while(m--){
scanf("%d %d %d",&u,&v,&d);
add(u,v,d);
add(v,u,d);
in[u]++;
}
topsort();
for(i = 0; i < n; i++)
dp[i][0] = dp[i][1] = inf; for(i = 0; i < n; i++)
work(sp[i]);
if(dp[0][1]==inf)dp[0][1] = -1;
printf("%d\n",dp[0][1]);
}
return 0;
}
ACdream 1083 有向无环图dp的更多相关文章
- BZOJ 1179 抢掠计划atm (缩点+有向无环图DP)
手动博客搬家: 本文发表于20170716 10:58:18, 原地址https://blog.csdn.net/suncongbo/article/details/81061601 https:// ...
- 湖南省第十二届大学生计算机程序设计竞赛 B 有向无环图 拓扑DP
1804: 有向无环图 Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 187 Solved: 80[Submit][Status][Web Board ...
- CSU 1804 - 有向无环图 - [(类似于)树形DP]
题目链接:http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1804 Bobo 有一个 n 个点,m 条边的有向无环图(即对于任意点 v,不存在从点 ...
- HDU 3249 Test for job (有向无环图上的最长路,DP)
解题思路: 求有向无环图上的最长路.简单的动态规划 #include <iostream> #include <cstring> #include <cstdlib ...
- 【学习笔记】有向无环图上的DP
手动博客搬家: 本文发表于20180716 10:49:04, 原地址https://blog.csdn.net/suncongbo/article/details/81061378 首先,感谢以下几 ...
- 2016 湖南省省赛B题《有向无环图》
题目链接[https://vjudge.net/problem/CSU-1804] 题意: 给出一个有向无环图,然后让你算下面的结果,count(i,j)表示i->j之间的路径条数. 题解: 根 ...
- HOJ 13845 Atomic Computer有向无环图的动态规划
考虑任意一个数字,任何一个都会有奇怪的..性质,就是一个可以保证不重复的方案——直接简单粗暴的最高位加数字..于是,如同上面的那个题:+1.-1.0 但是考虑到65536KB的标准内存限制,会得出一个 ...
- UVA_1025 a Spy in the Metro 有向无环图的动态规划问题
应当认为,有向无环图上的动态规划问题是动态规划的基本模型之一,对于某个模型,如果可以转换为某一有向无环图的最长.最短路径问题,则可以套用动态规划若干方法解决. 原题参见刘汝佳紫薯267页. 在这个题目 ...
- Uva11762 Race to 1——有向无环图&&记忆化搜索
题意 给出一个整数 $N$,每次可以在不超过 $N$ 的素数中等概率随机选择一个 $P$,如果 $P$ 是 $N$ 的约数,则把 $N$ 变成 $N/P$,否则 $N$ 不变.问平均情况下需要多少次随 ...
随机推荐
- 完善GDAL与OpenCV间的数据格式转换与影像分块读写
本博客为原创内容,未经博主允许禁止转载,商用,谢谢. 一.前言 关于GDAL与openCV间的数据格式转换,在我之前的博客中已有简要说明,这里,由于最近工作上经常用到openCV里的函数进行图像处理, ...
- python - 消息队列
消息队列分类 1.先进先出 2.后进先出 3.优先级队列 4.双向队列 1.先进先出 import queue q = queue.Queue(2) #队列最大长度 q.put(11) q.put(2 ...
- 用web技术开发出原生的App应用的体会(1)
本人是是个前端小白,学前端已经有半年的时间了,前几天开了个博客,希望记录自己学习历程的点滴. 今天要写的是关于用html,css,javascript等web技术开发原生的app应用. 总所周知,we ...
- (转)SQL Server2005 异常处理机制(Begin try Begin Catch)
begin try --SQL end trybegin catch --sql (处理出错动作) end catch我们将可能会出错的sql 写在begin try...end try 之间,若出 ...
- ios开发必备第三方库
引言 作为iOS开发人员,在开发App的过程中怎么会不使用第三方库呢?相信没有App是不使用第三方库的! 网络库 网络库,这是开发必备,除非你的App玩单机.现在特别火也特别好用的网络库就数AFNet ...
- 用C++写出hanoi
汉诺塔(港台:河內塔)是根据一个传说形成的數學问题有三根杆子A,B,C.A杆上有N个(N>1)穿孔圆盘,盘的尺寸由下到上依次变小.要求按下列规则将所有圆盘移至C杆:-每次只能移动一个圆盘-大的盘 ...
- vc 获取当前时间
1.使用CTime类 CString str; //获取系统时间 CTime tm; tm=CTime:: GetCurrentTime_r(); str=tm.Format("现在时间是% ...
- javascript-几个基础的排序算法
对这几个基础排序算法进行梳理,便于以后查看. /** * * 冒泡排序 * 从末尾开始相邻两数相互比较大小,满足条件就交换位置.循环每进行一次,即可确定第i位数的值. *冒泡排序的时间复杂度为O(n^ ...
- django解决跨域请求的问题
跨域请求可以用jsonp来解决,不过今天我发现一个很好用的包:django-cors-headers 只需要简单地配置一下就可 被请求方的setting.py中的配置如下: INSTALLED_APP ...
- js+jquery+html实现在三种不通的情况下,点击图片放大的效果
js+jquery+html实现在三种不通的情况下,点击图片放大的效果. 三种情况分别是:图片的父元素宽高固定; 图片的宽高固定; 图片的父元素宽固定,高度不固定 第一种情况:图片的父元素宽高固定 ...