思路:d(i, 0)表示从节点i到达大运村的最短路径,d(i, 1)表示从节点i到达大运村的次短路径。

1.最短路:当做DAG处理即可。

2.次短路:假设当前在u点处,下一个节点是v。v到终点的最短路是d(v, 0),次短路是d(v, 1),u到v的距离是w(u, v),只能封锁一条路,即只能删除一条边。分成两种情况:

a.将封锁用在了v点到达终点的路上,则此时GG拥有主动权,可以选择最小的路径,即Imin = min(w(u, v) + d(v, 1)),;

b.将封锁用在u-v这条路径上面,则此时城管拥有主动权,可以封锁最短路径,则GG这能选择次短路径Hmin。

则d(u, 1) = max(Imin, Hmin)

AC代码

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <utility>
#include <string>
#include <iostream>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define eps 1e-10
#define inf 0x3f3f3f3f
#define PI pair<int, int>
typedef long long LL;
const int maxn = 10000 + 5;
int n, m;
int d[maxn][2], in[maxn], Top[maxn], c[maxn*20];

struct Edge{
	int from, to, dist, nex;
	Edge() {}
	Edge(int u, int v, int d, int ne):from(u), to(v), dist(d), nex(ne){}
}edge[maxn*20];

int edgenum, head[maxn];
void add_edge(int u, int v, int dis) {
	edge[edgenum] = Edge(u, v, dis, head[u]);
	head[u] = edgenum++;
}

void topsort() { //逆向拓扑序
	queue<int>q;
	for(int i = 0; i < n; ++i) if(!in[i]) q.push(i);
	int num = 0;
	while(!q.empty()) {
		int u = q.front(); q.pop();
		for(int i = head[u]; i != -1; i = edge[i].nex) if(i&1){
			int v = edge[i].to;
			--in[v];
			if(!in[v]) q.push(v);
		}
		Top[num++] = u;
	}
}

void solve(int u) {
	if(u == n-1) {d[u][0] = d[u][1] = 0; return;} //终点
	int num = 0, Imin = inf;
	for(int i = head[u]; i != -1; i = edge[i].nex) if(!(i&1)){
		int v = edge[i].to;
		//最短路
		d[u][0] = min(d[u][0], d[v][0] + edge[i].dist);
		//次短路
		Imin = min(Imin, d[v][1] + edge[i].dist); // GG掌握主动权
		c[num++] = d[v][0] + edge[i].dist; //城管有主动权
	}
	if(num < 2) {d[u][1] = inf; return;} //GG无法到达从u到达终点
	int fir = c[0], sec = c[1]; //最小和次小
	if(fir > sec) swap(fir, sec);
	for(int i = 2; i < num; ++i) {
		if(c[i] <= fir) {
			sec = fir;
			fir = c[i];
		}
		else sec = min(sec, c[i]);
	}
	d[u][1] = max(Imin, sec);
	if(d[u][1] > inf) d[u][1] = inf;
	if(d[u][0] > inf) d[u][0] = inf;
}

int main() {
	int T;
	scanf("%d", &T);
	while(T--) {
		edgenum = 0;
		memset(head, -1, sizeof(head));
		memset(d, inf, sizeof(d));
		memset(in, 0, sizeof(in));
		scanf("%d%d", &n, &m);
		int u, v, dis;
		for(int i = 0; i < m; ++i) {
			scanf("%d%d%d", &u, &v, &dis);
			add_edge(u, v, dis);
			add_edge(v, u, dis);
			in[u]++;
		}
		topsort();
		for(int i = 0; i < n; ++i) {
			solve(Top[i]);
		}
		if(d[0][1] >= inf) printf("-1\n");
		else printf("%d\n", d[0][1]);
	}
	return 0;
} 

如有不当之处欢迎指出!

acdrem1083 人民城管爱人民 DP的更多相关文章

  1. ACdream 1083 人民城管爱人民

    拓扑排序,然后从终点开始递推. #pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio ...

  2. ACdream 1083 有向无环图dp

    题目链接:点击打开链接 人民城管爱人民 Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 128000/64000 KB (Java/Othe ...

  3. 机房人民大团结(DP)

    最近,机房出了一个不团结分子:Dr.Weissman.他经常欺骗同学们吃一种“教授糖豆”,使同学们神志不清,殴打他人,砸烂计算机,破坏机房团结.幸运地,一个和谐家认清了Dr.Weissman的本质.机 ...

  4. 【BZOJ-1040】骑士 树形DP + 环套树 + DFS

    1040: [ZJOI2008]骑士 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3312  Solved: 1269[Submit][Status ...

  5. 优化DP的奇淫技巧

    DP是搞OI不可不学的算法.一些丧心病狂的出题人不满足于裸的DP,一定要加上优化才能A掉. 故下面记录一些优化DP的奇淫技巧. OJ 1326 裸的状态方程很好推. f[i]=max(f[j]+sum ...

  6. 【BZOJ】1040: [ZJOI2008]骑士(环套树dp)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1040 简直不能再神的题orz. 蒟蒻即使蒟蒻,完全不会. 一开始看到数据n<=1000000就 ...

  7. bzoj 1040: [ZJOI2008]骑士 環套樹DP

    1040: [ZJOI2008]骑士 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1755  Solved: 690[Submit][Status] ...

  8. bzoj 1040: [ZJOI2008]骑士 树形dp

    题目链接 1040: [ZJOI2008]骑士 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3054  Solved: 1162[Submit][S ...

  9. 【环套树+树形dp】Bzoj1040 [ZJOI2008] 骑士

    Description Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬.最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争.战火 ...

随机推荐

  1. Log4j扩展使用--日志记录器Logger

    OK,现在我们认真的研究下Logger的配置,进行相关配置扩展. Log4j有三个主要的组件:Loggers(记录器),Appenders(输出源)和Layouts(布局).其中,Logger负责记录 ...

  2. WebRoot 与 webContent的区别

    Web项目发布到Tomcat中. 在Eclipse中生成项目是WebContent目录 而在MyEclipse中生成的项目目录名字好像叫做WebRoot,那么如果把MyEclipse的项目导入到Ecl ...

  3. Halcon一日一练:Halcon异常判断方法

    1.TryCatch tryCatch处理的方式如下: try *可能会出现错误的语句 .... catch(Exception) *获取错误代码 ErrorCode:=Exception[] **对 ...

  4. openstack开发基础

  5. fopen()函数参数

    摘自百度百科....     1."r" = "rt" 打开一个文本文件,文件必须存在,只允许读 2."r+" = "rt+&qu ...

  6. JavaWeb项目架构之Kafka分布式日志队列

    架构.分布式.日志队列,标题自己都看着唬人,其实就是一个日志收集的功能,只不过中间加了一个Kafka做消息队列罢了. kafka介绍 Kafka是由Apache软件基金会开发的一个开源流处理平台,由S ...

  7. python下用OpenCV的圆形检测

    写在文章前 这些天因为工作需要要学习图像检测,笨笨的我啥都不会要盯着OpenCV重头开始学(:′⌒`),甚至查资料能力都很弱弱〒▽〒 夸一下我最好的男票(*^▽^*)  男盆友也不是做图像处理的 但是 ...

  8. ABP 多租户 对应多数据库 租户启动报错

    什么是多租户? “软件多租户是指一个软件体系结构,其中一个软件实例在一个服务器上运行,并为多个租户提供服务*租户是一组共享具有软件实例特定权限的公共访问权限的用户. 架构中,软件应用程序旨在为每个租户 ...

  9. [快速傅立叶变换&快速傅里叶变换]【旧 手写笔记】

    $FFT$好美啊 参考资料: 1.算法导论 2.Miskcoo 3.Menci 4.虚数的意义-阮一峰 简单说一下,具体在下面的图片 实现: 可以用$complex$也可以手写 和计算几何差不多 注意 ...

  10. 链表回文判断(C++)

    题目描述: 对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构. 给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构.保证链表长度小于等 ...