【BZOJ2622】[2012国家集训队测试]深入虎穴 次短路

【BZOJ2622】[2012国家集训队测试]深入虎穴

Description

虎是中国传统文化中一个独特的意象。我们既会把老虎的形象用到喜庆的节日装饰画上,也可能把它视作一种邪恶的可怕的动物,例如“武松打虎”或者“三人成虎”。“不入虎穴焉得虎子”是一个对虎的威猛的形象的极好体现,而小强确偏偏进入了虎穴,但问题是怎么出来。
  有一个复杂的虎穴包括了N个节点(编号为0至N-1)和M条无向的通道,其中通道i(0<=i<M)连接两个节点R[i][0]和R[i][1],长为L[i]。有K个出口节点,分别为P[0], P[1]至P[K-1]。小强从0号节点出发,他想尽快到达一个出口节点。而洞穴中有一只会瞬间移动的老虎。小强每次到达一个节点,老虎就会瞬间移动到与这个节点相邻的某个通道里使得小强无法使用这个通道。不过,小强一旦选择了另一个没有被封锁的通道,老虎就不会在小强到达这个通道的目的地前改变位置。
  老虎非常聪明,它总能让小强离开洞穴所要消耗的时间最长。而小强也非常聪明,他能够计算出最快的逃生方案。
  为了让题目更加严谨,我们规定小强的逃生方案是如下的形式:对于每个节点X,给它的所有相邻的边<X,Y>指定一个权值f(X,Y),注意,f(X,Y)不等于f(Y,X);在一个节点,小强选择未被封锁的权值最大的通道逃生,直到到达出口。所有的f(X,Y)两两不同。
  你要计算小强的最快逃离时间T并输出。

Input

第一行三个整数 N M K
接下来M行 每行三个整数 表示一条无向边的两端和长度(无重边)
接下来K个整数 表示出口洞穴
输入直接保留这个就行

Sample Input

13 12 9
0 1 1
0 2 4
0 3 11
1 4 11
1 5 7
1 6 15
2 7 3
2 8 13
2 9 23
3 10 3
3 11 1
3 12 2
4 5 6 7 8 9 10 11 12

Sample Output

13

HINT

时间限制:3秒(包括系统读数据约1.1秒。函数中运行的时间限制约为1.9秒)
  空间使用注意:系统大约需要使用116M空间,因此你的程序的所能使用的空间不到400M。
  对前6个测试点,3<=N<=1000,M=N-1。
  对中间7个测试点,3<=N<=1000,2<=M<=100000。
  对最后7个测试点,3<=N<=100000,2<=M<=1000000。
  一共20个测试点。

题解:假设点i的答案是f[i],那么如果当前点u能走到若干个点v,那么老虎一定会封掉f[v]+L(u,v)最大的那个点,也就是说f[u]={f[v]+L(u,v)}中的次大值。

那么我们得到做法:先令出口的答案为1,然后对于求出出口周围所有点到出口距离的次大值,然后在用这个次大值不断更新其他点的次大值。发现这个算法满足贪心性质,可以用Dij求最短路。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <utility>
using namespace std;
const int maxn=100010;
const int maxm=1000010;
int n,m,k,cnt;
int to[maxm<<1],next[maxm<<1],head[maxn],val[maxm<<1],vis[maxn];
struct node
{
	int x,y;
	node() {x=y=1<<30;}
	node(int a,int b) {x=a,y=b;}
	bool operator < (const node &a) const
	{
		return (y==a.y)?(x>a.x):(y>a.y);
	}
}dis[maxn];
priority_queue<pair<node,int> > q;
inline void add(int a,int b,int c)
{
	to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt++;
}
inline int rd()
{
	int ret=0,f=1;	char gc=getchar();
	while(gc<'0'||gc>'9')	{if(gc=='-')	f=-f;	gc=getchar();}
	while(gc>='0'&&gc<='9')	ret=ret*10+(gc^'0'),gc=getchar();
	return ret*f;
}
int main()
{
	n=rd(),m=rd(),k=rd();
	int i,u,a,b,c;
	memset(head,-1,sizeof(head));
	for(i=1;i<=m;i++)	a=rd(),b=rd(),c=rd(),add(a,b,c),add(b,a,c);
	for(i=1;i<=k;i++)	a=rd(),dis[a]=node(0,0),q.push(make_pair(dis[a],a));
	while(!q.empty())
	{
		u=q.top().second,q.pop();
		if(vis[u])	continue;
		vis[u]=1;
		for(i=head[u];i!=-1;i=next[i])	if((dis[u].y+val[i])<dis[to[i]].y)
		{
			if(dis[to[i]].x>dis[u].y+val[i])	dis[to[i]].y=dis[to[i]].x,dis[to[i]].x=dis[u].y+val[i];
			else	dis[to[i]].y=dis[u].y+val[i];
			q.push(make_pair(dis[to[i]],to[i]));
		}
	}
	printf("%d",dis[0].y);
	return 0;
}
posted @ 2017-11-10 10:58  CQzhangyu  阅读(595)  评论(0编辑  收藏  举报