NOIP2013模拟】DY引擎 题解+代码
2016-06-22 19:14
351 查看
Description
BOSS送给小唐一辆车。小唐开着这辆车从PKU出发去ZJU上课了。众所周知,天朝公路的收费站超多的。经过观察地图,小唐发现从PKU出发到ZJU的所有路径只会有N(2<=N<=300)个不同的中转点,其中有M(max(0, N-100) <=M<=N)个点是天朝的收费站。N个中转点标号为1…N,其中1代表PKU,N代表ZJU。中转点之间总共有E(E<=50,000)条双向边连接。
每个点还有一个附加属性,用0/1标记,0代表普通中转点,1代表收费站。当然,天朝的地图上面是不会直接告诉你第i个点是普通中转点还是收费站的。地图上有P(1<=P<=3,000)个提示,用[u, v, t]表示:[u, v]区间的所有中转点中,至少有t个收费站。数据保证由所有标记得到的每个点的属性是唯一的。
车既然是BOSS送的,自然非比寻常了。车子使用了世界上最先进的DaxiaYayamao引擎,简称DY引擎。DY引擎可以让车子从U瞬间转移到V,只要U和V的距离不超过L(1<=L<=1,000,000),并且U和V之间不能有收费站(小唐良民一枚,所以要是经过收费站就会停下来交完钱再走)。
DY引擎果然是好东西,但是可惜引擎最多只能用K(0<=K<=30)次。
Input
第一行有6个整数N,M,E,P,L,K分别代表:N个中转点,M个收费站,E条边,P个提示,DY引擎的有效距离L,DY引擎的使用次数K。接下去E行,每行有3个整数u,v,w(1<=u, v<=N; 1<=w<=1,000,000)表示:u和v之间有一条长度为w的双向边。
接下去P行,每行有3个整数u,v,t(1<=u<=v<=N; 0<=t<=u-v+1)表示: [u, v] 标号区间至少有t个收费站。
Output
输出一个整数,表示小唐从PZU开到ZJU用的最短距离(瞬间转移距离当然是按0来计算的)。Sample Input
6 2 6 2 5 11 2 1
2 3 2
3 6 3
1 4 1
4 5 2
5 6 3
2 5 2
4 6 2
Sample Output
1【样例解释】
4、5是收费站。1->2(1)->6(1)
Data Constraint
对于30%的数据保证:2<=N<=30,max(0, N-10) <=M<=N,0<=k<=10
对于100%的数据保证:
2<=N<=300,max(0, N-100) <=M<=N,E<=50,000,1<=P<=3,000,1<=L<=1,000,000,0<=K<=30
Solution
其实呢,这道题是由两道小题拼起来的。1.对于一些约束,判断每个点是否为关键点
设s[i]表示1~i中收费站的数量,那么第i个点的状态即为s[i]-s[i-1]那么它给出的条件([u, v] 标号区间至少有t个收费站)就是
s[v]−s[u−1]>=t
隐含条件
s[i]−s[i−1]>=0
s[i−1]−s[i]>=−1
那么按照查分约束那样,连边构图,从0开始求最长路即可。
详细可以点这里
单元最短路*1
2.在神奇条件的情况下求最短路
分为两步首先,两个点如果能互相通过引擎飞过去,那么距离为0,预处理一下即可。N<=300那就Floyd做完。枚举k时注意判断k不是收费站
多元最短路*1
接着做最短路,单元最短路*2
搞定
Code
#include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #define N 1000 #define fo(i,a,b) for(int i=a;i<=b;i++) using namespace std; int a[N][N],b[N][N],c[N][N],s[N],n,m,e,p,l,kk,next[500000],last[500000],to[500000],data[500000],dd[5000000],d[5000000][2],tot=0; void putin(int x,int y,int z) { next[++tot]=last[x];last[x]=tot;to[tot]=y;data[tot]=z; } int main() { scanf("%d%d%d%d%d%d",&n,&m,&e,&p,&l,&kk); fo(i,1,n) fo(j,1,n) a[i][j]=1000000000; fo(i,1,e) { int x,y,z;scanf("%d%d%d",&x,&y,&z); z=min(z,a[x][y]); c[x][y]=c[y][x]=a[x][y]=a[y][x]=z; } fo(i,1,p) { int x,y,z;scanf("%d%d%d",&x,&y,&z); putin(x-1,y,z); } fo(i,1,n) putin(i-1,i,0),putin(i,i-1,-1); { int i=0,j=1,bz ;dd[1]=0; memset(s,128,sizeof(s));s[0]=0;memset(bz,0,sizeof(bz));bz[0]=1; for(;i<j;) { int x=dd[++i]; for(int k=last[x];k;k=next[k]) { if (s[to[k]]<s[x]+data[k]) { s[to[k]]=s[x]+data[k]; if (bz[to[k]]==0) { dd[++j]=to[k];bz[to[k]]=1; } } } bz[x]=0; } } for(int i=n;i;i--) s[i]=s[i]-s[i-1]; fo(k,1,n) if (s[k]!=1) { fo(i,1,n) if(i!=k) fo(j,1,n) if(i!=j && j!=k) { a[i][j]=min(a[i][j],a[i][k]+a[k][j]); // if (a[i][j]<=l) b[i][j]=b[j][i]=1; } } int f [40],bz ;int i=0,j=1; fo(i,1,n) if(b[1][i]==1) printf("%d\n",i); d[1][0]=1;d[1][1]=0;memset(f,127,sizeof(f));memset(bz,0,sizeof(bz));f[1][0]=0;bz[1][0]=1; for(;i<j;) { int x=d[++i][0]; fo(y,1,n) { if (c[x][y]>0 && f[y][d[i][1]]>f[x][d[i][1]]+c[x][y]) { f[y][d[i][1]]=f[x][d[i][1]]+c[x][y]; if (bz[y][d[i][1]]==0) { d[++j][0]=y;d[j][1]=d[i][1];bz[y][d[i][1]]=1; } } if (d[i][1]<kk && a[x][y]<=l && f[y][d[i][1]+1]>f[x][d[i][1]]) { f[y][d[i][1]+1]=f[x][d[i][1]]; if (bz[y][d[i][1]+1]==0) { d[++j][0]=y;d[j][1]=d[i][1]+1;bz[y][d[j][1]]=1; } } } bz[x][d[i][1]]=0; } int ans=2147483647; fo(i,0,kk) ans=min(ans,f [i]); printf("%d\n",ans); }
相关文章推荐
- Java IO流学习总结
- python学习之 字符串前'r'的用法
- java乱码问题
- java sleep与wait区别
- 线性表的顺序存储结构C语言版
- diffcount统计两个版本之间代码变更行数
- YII 框架学习[1] —— 引入Yii框架
- 线性表的链式存储C语言版
- Python正则表达式
- Java中OutOfMemoryError(内存溢出)的三种情况及解决办法
- (java 一) 断言 assert的使用
- 解决weblogic错误:java.sql.SQLRecoverableException: IO Error: Broken pipe
- Python 描述符(descriptor) 杂记
- Geekban极客班C++STL与泛型编程 第二周
- java 正则表达式
- python mysql
- 一:Java 并发和多线程的介绍
- java端RESTful web services的几种实现方式
- Teechart在VC++中使用的碎碎念
- Spring IOC为什么可以实现解耦