NOIP模拟 边的处理【分治+动态规划】
来源:互联网 发布:淘宝确认收货是什么 编辑:程序博客网 时间:2024/06/08 09:30
题目描述
有一个n个点的无向图,给出m条边,每条边的信息形如
给出q组询问形如
接下来解释询问以及边的意义。
询问表示,一开始你在点u上,然后按顺序处理编号从1到r的边。
对于一条边
1、如果你当前在x点或者y点上,那么你可以走这条边(从x到y或从y到x)并付出c的代价(当然你也可以不走,看操作2)。
2、如果你不走这条边或者不可以走这条边(即你当前不在x或y上),那么你需要付出r的代价。
询问如果要从点u开始,按顺序处理完编号从l到r的边之后到达点v的最小代价,如果不能到达v,那么输出−1
n≤30,m≤20000,q≤200000
解题思路:
对于单独的一个询问,我们可以用dp[i][x][y]表示处理了l~i这几条边,动态规划出从x到y的最小代价,这样的复杂度是
注意到若有两个询问区间有重合我们重复了许多状态,所以想到了分治。
对于每个分治点中心mid,并用f[i][x][y]动规计算处理了i到mid的边从x到y的最小代价,同样用g[i][x][y]维护处理了mid+1到i的边从x到y的最小代价,那对于所有区间经过了mid的询问
接着在分治处理r
时间复杂度
#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<cmath>#include<vector>#include<queue>#define ll long longusing namespace std;int getint(){ int i=0,f=1;char c; for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar()); if(c=='-')f=-1,c=getchar(); for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0'; return i*f;}const int N=35,M=20005;const int INF=0x3f3f3f3f;struct node{ int s,t,l,r,id;}q[200005],d[200005];struct edge{ int x,y,w1,w0;}bian[M];int n,m,Q;int ans[200005],f[M][N][N],g[M][N][N];void solve(int l,int r,int L,int R){ if(l>r||L>R)return; int mid=l+r>>1; int i,x,y; for(i=l-1;i<=r+1;i++) for(x=1;x<=n;x++) for(y=1;y<=n;y++) f[i][x][y]=g[i][x][y]=INF; for(x=1;x<=n;x++)f[mid+1][x][x]=0; for(i=mid;i>=l;i--) for(x=1;x<=n;x++) { f[i][x][x]=f[i+1][x][x]+bian[i].w0; for(y=1;y<=n;y++) { if(x==bian[i].x) f[i][x][y]=min(f[i][x][y],f[i+1][bian[i].y][y]+bian[i].w1); if(x==bian[i].y) f[i][x][y]=min(f[i][x][y],f[i+1][bian[i].x][y]+bian[i].w1); f[i][x][y]=min(f[i][x][y],f[i+1][x][y]+bian[i].w0); } } for(x=1;x<=n;x++)g[mid][x][x]=0; for(i=mid+1;i<=r;i++) for(x=1;x<=n;x++) { g[i][x][x]=g[i-1][x][x]+bian[i].w0; for(y=1;y<=n;y++) { if(y==bian[i].x) g[i][x][y]=min(g[i][x][y],g[i-1][x][bian[i].y]+bian[i].w1); if(y==bian[i].y) g[i][x][y]=min(g[i][x][y],g[i-1][x][bian[i].x]+bian[i].w1); g[i][x][y]=min(g[i][x][y],g[i-1][x][y]+bian[i].w0); } } int R1=L-1,L1=R+1; for(i=L;i<=R;i++) { if(q[i].l<=mid&&mid<=q[i].r) for(x=1;x<=n;x++) ans[q[i].id]=min(ans[q[i].id],f[q[i].l][q[i].s][x]+g[q[i].r][x][q[i].t]); else if(q[i].r<mid)d[++R1]=q[i]; else if(q[i].l>mid)d[--L1]=q[i]; } for(int i=L;i<=R;i++) q[i]=d[i]; solve(l,mid-1,L,R1); solve(mid+1,r,L1,R);}int main(){ //freopen("lx.in","r",stdin); n=getint(),m=getint(),Q=getint(); for(int i=1;i<=m;i++) { bian[i].x=getint(),bian[i].y=getint(); bian[i].w1=getint(),bian[i].w0=getint(); } for(int i=1;i<=Q;i++) { q[i].s=getint(),q[i].t=getint(); q[i].l=getint(),q[i].r=getint(); q[i].id=i,ans[i]=INF; } solve(1,m,1,Q); for(int i=1;i<=Q;i++) if(ans[i]==INF)puts("-1"); else cout<<ans[i]<<'\n'; return 0;}
阅读全文
0 0
- NOIP模拟 边的处理【分治+动态规划】
- NOIP模拟:边的处理(分治)
- NOIP模拟 杆子的排列 【动态规划】
- [NOIP模拟][动态规划]permut
- [NOIP模拟][动态规划]hello
- NOIP模拟 table 动态规划
- [NOIP模拟][动态规划]Table
- 【哈希】【动态规划】[NOIP模拟赛]仔细的检查
- 【动态规划】[NOIP 模拟赛]密码
- [NOIP模拟][动态规划]随机图
- NOIP模拟 分玩具【博弈论】【动态规划】
- NOIP模拟 Game 【博弈论】【动态规划】
- NOIP模拟 回文子串【动态规划】
- NOIP模拟题 2016.11.11 [搜索] [动态规划] [网络流] [字符串处理]
- NOIP模拟题 2016.11.14 [动态规划] [线段树优化DP] [字符串的复制粘贴DP]
- 【动态规划】【图论】[NOIP模拟赛]独立集
- NOIP模拟题 2016.9.10 [动态规划] [概率] [贪心]
- [NOIP模拟][记忆化搜索][动态规划]游戏
- 【百度地图API】如何利用自己的数据制作社交地图?只显示可视区域内的标注
- Maven的简介,Maven工程搭建POM,坐标
- Netty源码分析:accept
- Jupyter notebook 安装,初步使用
- NOIP 2017 赛前集训总结 C++版
- NOIP模拟 边的处理【分治+动态规划】
- Jsp文件上传
- 有一个字符数组的内容为:"student a am i",请你将数组的内容改为"i am a student"
- 【UnityShader入门精要】Unityshader中的漫反射(逐像素漫反射diffuse)
- 芯片史上最大收购案!会发生吗?
- windows环境下python2.7、pycharm、numpy_mkl、scipy、sklearn、Matplotlib、jupyter完整安装教程
- JS中的Window对象、Parent对象、Frame对象、Document对象和Form对象
- python测试开发笔/面试题(含答案)
- Linux入门笔记2. 文件系统概览