题目我也不说来源哪里了,但是还是希望大家可以来我的OJ做一下吧。 这题就是一个DP+Spfa,具体怎么想到的?我也不知道,做着做着就对了。 就是用一个数组判断到这个时间总共停了多少回合,然后前后两个时间相减为0就代表这一段时间之内可以通过这一个点,就是没有封。然后跑一次spfa就好。#include<map> #include<queue> #include<cmath> #include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define qread(x) x=read() #define mes(x,y) memset(x,y,sizeof(x)) #define mpy(x,y) memcpy(x,y,sizeof(x)) #define Maxn 100 #define INF 2147483647 inline int read(){ char ch=getchar(); int f=1,x=0; 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; } int n,m,K,e,D,x,y,c; struct Edge{ int x,y,c,next; }E[Maxn*Maxn+1];int len,first[Maxn+1]; void ins(int x,int y,int c){ len++; E[len].x=x;E[len].y=y;E[len].c=c; E[len].next=first[x];first[x]=len; } int d[Maxn+1],map[Maxn+1][Maxn+1];bool v[Maxn+1]; std::queue<int>q; int bfs(int st,int ed){ q.push(1); for(int i=1;i<=m;i++)d[i]=999999;d[1]=0; mes(v,false);v[1]=true; while(q.empty()==false){ x=q.front(); for(int k=first[x];k>0;k=E[k].next){ y=E[k].y; if(map[y][ed]-map[y][st-1]==0&&d[y]>d[x]+E[k].c){ d[y]=d[x]+E[k].c; if(v[y]==false){ v[y]=true; q.push(y); } } } v[x]=false; q.pop(); } return d[m]; } int f[Maxn+1]; int main(){ qread(n);qread(m);qread(K);qread(e); mes(map,0); for(int i=1;i<=e;i++){ qread(x);qread(y);qread(c); if(map[x][y]==0||map[x][y]>c)map[x][y]=map[y][x]=c; } len=0;mes(first,0); for(int i=1;i<=m;i++){ for(int j=i+1;j<=m;j++){ if(map[i][j]>0){ ins(i,j,map[i][j]); ins(j,i,map[j][i]); } } } qread(D); mes(map,0); for(int i=1;i<=D;i++){ qread(c),qread(x);qread(y); for(int j=x;j<=y;j++)map[c][j]=1; } for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++){ map[i][j]+=map[i][j-1]; } } f[0]=0; for(int i=1;i<=n;i++){ f[i]=INF; for(int j=1;j<=i;j++){ int tmp=bfs(j,i); if(f[i]>f[j-1]+tmp*(i-j+1)+K)f[i]=f[j-1]+tmp*(i-j+1)+K; } } printf("%d\n",f[n]-K); }
查看原文:http://hz2016.tk/blog/?p=61
[ZJOI2006]物流运输
最新推荐文章于 2022-07-11 13:12:50 发布