DTOJ 4001 分身术(orz)

版权声明:神犇使用记得标明出处哦QAQ https://blog.csdn.net/qq_41717018/article/details/83510758

分身术
时间限制: 1 Sec 内存限制: 256 MB
题目描述

题目背景:当您再次回到机房时已经是中午了,于是您决定去吃饭。

从机房到食堂的地图可以简化为一张 n n 个点, m m 条边的有向图,通过每条边需要一定的时间。机房在1号节点,食堂在n号节点。膜法师 h e r c i e r hercier 使用结界将食堂和一些点封锁了起来使其无法通过,如果想通过某个节点,你就必须破坏掉维持这个节点结界的所有结界发生器。幸运的是,你在上一题的未知森林里领悟了分身术,你可以分出无限多的分身去破坏结界发生器, n o r m a l g o d normalgod 想知道你最早什么时候能到达食堂,请你写个程序告诉他。(破坏瞬间完成,分身移动速度与本体相同)

输入
第一行 2 2 个整数,分别表示 n , m n,m

之后 m m 行每行三个整数 a , b , c a,b,c ,表示 a a b b 有一条需要走 c c 分钟的边。
之后 n n 行每行一个正整数 k k 表示维持这个节点结界的结界发生器数目。

之后 k k 1 n 1-n 之间的节点编号,表示每个结界发生器的位置。
输出
到达食堂的最早时间,永远不能到达输出 1 -1
样例输入
6 6
1 2 1
1 4 3
2 3 1
2 5 2
4 6 2
5 3 2
0
0
0
1 3
0
2 3 5
样例输出
5
提示
对于20% 的数据,满足 n 15 , m 50 n≤15,m≤50
对于50% 的数据,满足 n 500 , m 6000 n≤500,m≤6000
对于另20% 的数据,满足 k = 0 k=0
对于100% 的数据,满足 n 3000 , m 70000 , 1 c 1 0 8 n≤3000,m≤70000,1≤c≤10^8。

连接两个节点的道路可能不止一条, 也可能存在一个节点自己到自己的道路。

题解:
k = = 0 k==0 时,实际上就是一个从 1 1 n n 之间的最短路。
k ! = 0 k!=0 时,考虑这些会带来限制的点。
对于单独一个被限制的点,与之相关的一个子图,你只能按照拓扑序将它一个一个点消掉。
设一个点到 1 1 的最短路为 d i s i dis_{i} ,与之相关的就是在他所在子图上拓扑序与之相关的点。
于是我们在做最短路 d i j k s t r a dijkstra 中,往下转移作拓扑排序。
h x h_{x} 就表示在 x x 点,在拓扑序与之相邻的点转移来的 d i s dis 值。
并且只有当某个点入度为 0 0 时才会进优先队列。

#include<bits/stdc++.h>
using namespace std;
#define in inline
#define re register
#define rep(i,a,b) for(re int i=a;i<=b;i++)
#define repd(i,a,b) for(re int i=a;i>=b;i--)
#define For(i,a,b) for(re int i=a;i<b;i++)
#define _(d) while(d(isdigit(ch=getchar())))
template<class T>in void g(T&t){T x,f=1;char ch;_(!)ch=='-'?f=-1:f;x=ch-48;_()x=x*10+ch-48;t=f*x;}
typedef long long ll;
const int N=6004,M=14e4+4;
struct E{int to,nxt;ll w;}e[M<<1];
int head[N],tot,d[N];
in void ins(int x,int y,ll z){
	e[++tot]=E{y,head[x],z},head[x]=tot;
}
ll h[N],n,m,ind[N],out[N],dis[N],inf,faq[N];
typedef pair<ll,int>P;
vector<int>v[N];bool vis[N];
#define mk(a,b) make_pair((a),(b))
#define fi first
#define se second
in void dj(){
	priority_queue<P,vector<P>,greater<P> >q;
	memset(dis,0x3f,sizeof(dis));inf=dis[2];dis[1]=0;
	q.push(mk(0,1));
	while(!q.empty()){
		P now=q.top();q.pop();
		int x=now.se;
		if(vis[x]) continue; vis[x]=1;
		For(i,0,v[x].size()){
			int to=v[x][i];ind[to]--; 
			faq[to]=max(faq[to],dis[x]);
			if(!ind[to]&&dis[to]!=inf){
				dis[to]=max(dis[to],faq[to]);
				q.push(mk(dis[to],to));
				
			}
		}
		for(int i=head[x];i;i=e[i].nxt){
			dis[e[i].to]=max(dis[e[i].to],faq[e[i].to]);
			if(dis[e[i].to]>dis[x]+e[i].w){
				dis[e[i].to]=dis[x]+e[i].w;
				if(!ind[e[i].to]) q.push(mk(dis[e[i].to],e[i].to));
			}
		}
	}
}
int main(){
	//freopen(".in","r",stdin);freopen(".out","w",stdout);
	g(n),g(m);
	rep(i,1,m){
		int x,y,z;
		g(x),g(y),g(z);
		ins(x,y,z);
	}
	rep(i,1,n){
		int t;g(t);
		if(i==1&&t) return puts("-1");
		while(t--){
			int x; g(x);
			v[x].push_back(i);
			ind[i]++;
		}
	}dj();
	return !printf("%lld\n",(dis[n]>=inf)?-1:dis[n]);
}

猜你喜欢

转载自blog.csdn.net/qq_41717018/article/details/83510758