LuoguP1119 灾后重建

  1. Dijkstra 做法:TLE 3个点,70pts (O2) , 复杂度 \(O(n^3\ log\ m)\), \(\Theta(n^3\ log\ m\ +\ Qn)\) 可优化至 \(\Theta(\ n^3\ log\ m\ +\ n)\), 懒得写了。

代码:

//Dijkstra Version
#include<stdio.h>
#include<queue>
#include<vector>
#include<cstring>
//#pragma GCC optimize(2)
using namespace std;
inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0' && ch<='9')
        x=x*10+ch-'0',ch=getchar();
    return x*f;
}
const int N=205,INF=(1<<30)-1+(1<<30);
int t[N],n,m,dist[N][N][N];
bool reb[N],vis[N]={};
struct edge{
	int v,w;
	edge(int v,int w):v(v),w(w){}
};vector<edge>e[N];
struct node{
	int u,dis;
	node(int u,int dis):u(u),dis(dis){}
	bool operator <(const node &a)const{return dis>a.dis;}
};
void Dijkstra(int s,int time){
	memset(vis, 0, sizeof(vis));
	for(int i=1;i<=n;i++)dist[time][s][i]=dist[time][i][s]=INF;
	if(!reb[s])return;
	dist[time][s][s]=0;
	priority_queue<node>q;
	q.push(node(s,0));
	while(!q.empty()){
		int u=q.top().u;q.pop();//printf("%d %d\n",u,vis[u]);
		int len=e[u].size();
		if(!vis[u]){
			vis[u]=1;
			for(int i=0;i<len;i++){
				int v=e[u][i].v,w=e[u][i].w;
				if(!vis[v]&&reb[v]&&dist[time][s][v]>dist[time][s][u]+w){
					dist[time][s][v]=dist[time][v][s]=dist[time][s][u]+w;
					q.push(node(v,dist[time][s][v]));
				}
			}
		}
	}
}
int normalfind(int x){
	int i,sum=0;
	for(i=1;i<=n;i++){
		if(t[i]>x)break;
		if(t[i]==t[i+1]&&i<n)sum--;
	}return sum+i-1;
}
signed main(){
//	freopen("P1119_2.in","r",stdin);
//	freopen("a.out","w",stdout);
	int u,v,w,x,y,z;
	n=read(),m=read();
	for(int i=1;i<=n;i++)t[i]=read();
	for(int i=1;i<=m;i++){
		u=read(),v=read(),w=read();u++,v++;
		e[u].push_back(edge(v,w));
		e[v].push_back(edge(u,w));
	}
	for(int i=1,top=0;i<=n;i++){
		top++;
		reb[i]=1;
		while(i<n&&t[i]==t[i+1])reb[++i]=1;
		for(int j=1;j<=n;j++)
			Dijkstra(j,top);
	}
	int q;
	q=read();
	while(q--){
		x=read(),y=read(),z=read();x++,y++;
		z=normalfind(z);
		if(z==0||dist[z][x][y]>=INF-3)puts("-1");
		else printf("%d\n",dist[z][x][y]);
	}
	return 0;
}
  1. 正解 Floyd 做法 复杂度 \(O(n^3)\), \(\Theta(n^3\ +\ n)\)

代码很好理解,如果看了下面代码还没懂可以戳题解 题解

关键点是 t 是不下降序列,询问给出的 t 也是不下降的,所以容易想到顺序求解。但是题目完全可以给你乱序的,这就要离线排序做了。

AC代码:

//Floyd Version
#include <bits/stdc++.h>
using namespace std;
const int INF=1e8,N=210;
int f[N][N],lim;
int n,m,q,t[N],u,v,w,x,y,times;
int main(){
	scanf("%d%d",&n,&m);
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
			f[i][j]=INF;
	for(int i=0;i<n;i++)scanf("%d",&t[i]),f[i][i]=0;
	while(m--)scanf("%d%d%d",&u,&v,&w),f[u][v]=f[v][u]=w;
	scanf("%d",&q);
	while(q--){
		scanf("%d%d%d",&u,&v,&w);
		for(int k=lim;k<n&&t[k]<=w;k++,lim++)
			//在线顺序求解,一个一个放入
			for(int i=0;i<n;i++)
				for(int j=0;j<n;j++)
					f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
		if (t[u]<=w&&t[v]<=w&&f[u][v]<INF)
			printf("%d\n",f[u][v]);
		else puts("-1");
	}
	return 0;
}
posted @ 2022-11-12 10:48  robinyqc  阅读(30)  评论(0)    收藏  举报