题解:洛谷P1119 灾后重建

题解:洛谷P1119 灾后重建

题目传送门

前言:没有掌握floyed求最短路的精髓是每次增加选一个中转点,导致写了2h才勉强卡过

法1:最暴力的想法就是开个三维数组把前i个点的dis状态全部存下来,跑N次floyed,当然由于每次点数时递增的,所以实际复杂度远远小于O(N^4),算了下大概200个点跑了4e8多一点点,卡卡常开O2还是能过(不吸氧只有40,逃)

#include<bits/stdc++.h>
#define ri register int
#define F(i,l,r) for(ri i=l;i<=r;++i)
using namespace std;
char buf[1<<19],*p1=buf,*p2=buf;
inline int gc(){ return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,1<<19,stdin),p1==p2)?EOF:*p1++; }
inline int rd(){
	ri x=0; char ch=gc();
	while(!isdigit(ch)) ch=gc();
	while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=gc();
	return x;
}
const int inf=0x3f3f3f3f;
int n,m,q,t[205],g[100003],dis[202][202][202];//g[i]:t=i时的点数 
inline void ini(){
	memset(dis,0x3f,sizeof(dis)); F(i,0,n-1) F(j,0,n-1) dis[j][j][i]=0;
	F(i,1,n-2) F(j,t[i],t[i+1]-1) g[j]=i;
	F(i,0,t[0]-1) g[i]=-1; F(i,t[n-1],100000) g[i]=n-1;
}
int main(){
//	freopen("a.in","r",stdin);
//	freopen("a.out","w",stdout);
	int u,v,ti;  n=rd(),m=rd(); F(i,0,n-1) t[i]=rd();
	ini();
	F(i,1,m) u=rd(),v=rd(),ti=rd(),dis[u][v][0]=ti,dis[v][u][0]=ti;
	F(p,0,n-1){
		if(p>0) F(i,0,n-1) F(j,0,n-1) dis[i][j][p]=dis[i][j][p-1];
		F(k,0,p) F(i,0,p) F(j,0,p) dis[i][j][p]=min(dis[i][k][p]+dis[k][j][p],dis[i][j][p]);
	}
	q=rd(); while(q--){
		u=rd(),v=rd(),ti=rd();
		if(g[ti]<0 || u>g[ti] || v>g[ti] || dis[u][v][g[ti]]==inf) puts("-1");
		else printf("%d\n",dis[u][v][g[ti]]);
	}
	return 0;
}

法2:

1.留意到法1中的做法其实很浪费:第p轮更新却要把前p-1轮重复的再算一遍,能不能优化呢?

2.发现每次随时间新加进来点k后,可能被改变的dis其实只有过了k点的dis,我们惊讶地发现这不就是以k为中转站去更新dis吗?前k-1个点作为中转站的dis是不受影响的。所以每次询问都把当前 t 新修好的点加入最短路更新 dis 即可,不用每次重新算。

3.再结合floyed的本质:外层k的累加,代表着允许前1个点作为中转站,前2个点,前3个点...前k个点来更新dis状态, 用一句话概括就是:从i号顶点到j号顶点只经过前k号点的最短路程。

4.题上询问的t又是递增的,所以在线加点没有问题,这样dis只用开两维,时间复杂度O(N^3)

...
inline void upd(int k){
	F(i,0,n-1) F(j,0,n-1) dis[i][j]=min(dis[i][k]+dis[k][j],dis[i][j]);
}
int main(){
	...
	int nw=0;
	q=rd(); while(q--){
		u=rd(),v=rd(),ti=rd();
		while(t[nw]<=ti && nw<n) upd(nw++); 
		if(t[u]>ti || t[v]>ti || dis[u][v]==inf) puts("-1");
		else printf("%d\n",dis[u][v]);
	}
}
posted @ 2023-10-08 11:45  superl61  阅读(25)  评论(0)    收藏  举报