1817 灾后重建
暴力:
//暴力spfa模拟 60分(40%TLE) #include<cstdio> #include<cstring> #include<queue> #include<iostream> using namespace std; inline int read(){ register int x=0;bool f=1; register char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=0;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return f?x:-x; } const int N=210; int n,m,cas,tot,dis[N],t[N],head[N]; bool vis[N]; struct node{ int v,w,next; }e[N*N]; void add(int x,int y,int z){ e[++tot].v=y; e[tot].w=z; e[tot].next=head[x]; head[x]=tot; } int query(int S,int T,int lim){ if(t[S]>lim||t[T]>lim) return -1; if(S==T) return 0; memset(dis,0x3f3f3f3f,sizeof dis); memset(vis,0,sizeof vis); queue<int>q; q.push(S); vis[S]=1;dis[S]=0; while(!q.empty()){ int x=q.front();q.pop(); vis[x]=0; for(int i=head[x];i;i=e[i].next){ int v=e[i].v,w=e[i].w; if(t[v]>lim) continue; if(dis[v]>dis[x]+w){ dis[v]=dis[x]+w; if(!vis[v]){ vis[v]=1; q.push(v); } } } } if(dis[T]==0x3f3f3f3f) return -1; else return dis[T]; } int main(){ n=read();m=read(); for(int i=0;i<n;i++) t[i]=read(); for(int i=1,x,y,z;i<=m;i++){ x=read();y=read();z=read(); add(x,y,z);add(y,x,z); } cas=read(); for(int x,y,z;cas--;){ x=read();y=read();z=read(); printf("%d\n",query(x,y,z)); } return 0; }
正解:
加深了对floyed的理解
实质是dp
d[k][i][j] 表示i-j只经过0-k的节点作为中间点的最短路
有两种情况 走或者不走k
f[k][i][j]=min(f[k-1][i][j],f[k-1][i][k]+f[k-1][k][j])
可以压缩空间压掉第一维
那就用floyed搞就好了. 首先t是小到大的 还有就是输入数据时不降的 结合题目每次询问i->j 保证中间经过的一定是修好了的城市 只要满足 经过的在这之前都修好了 那根据对floyed的理解 保证循环k<=t就好了
AC代码:
#include<cstdio> #include<cstring> #include<iostream> using namespace std; inline int read(){ register int x=0;bool f=1; register char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=0;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return f?x:-x; } const int N=210; int n,m,cas,t[N]; int f[N][N]; int k=0; int query(int S,int T,int lim){ if(t[S]>lim||t[T]>lim) return -1; for(;k<n&&t[k]<=lim;k++){ 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(f[S][T]==0x3f3f3f3f) return -1; else return f[S][T]; } int main(){ memset(f,0x3f3f3f3f,sizeof f); n=read();m=read(); for(int i=0;i<n;i++) t[i]=read(); for(int i=0;i<n;i++) f[i][i]=0; for(int i=1,x,y,z;i<=m;i++){ x=read();y=read();z=read(); f[x][y]=f[y][x]=z; } cas=read(); for(int x,y,z;cas--;){ x=read();y=read();z=read(); printf("%d\n",query(x,y,z)); } return 0; }