题目

有一个n个点的无向图,给出m条边,每条边的信息形如\(<x,y,c,r>\)

给出q组询问形如\(<u,v,l,r>\)

接下来解释询问以及边的意义

询问表示,一开始你在点u上,然后按顺序处理编号从l到r的边

对于一条边\(<x,y,c,r>\),你可以进行两种操作:

如果你当前在x点或者y点上,那么你可以走这条边(从x到y或从y到x)并付出c的代价(当然你也可以不走,看操作2)

如果你不走这条边或者不可以走这条边(即你当前不在x或y上),那么你需要付出r的代价询问如果要从u点开始,按顺序处理完编号从l到r的边之后到达v点的最小代价,如果不能到达v,那么输出-1。

边和点的编号从1开始

分析

考虑分治,

当前做到区间[l,r],mid=(l+r)/2

设lf[i][x][y]表示在左区间中从x点开始,经过了i到mid的边,最后走到了y的最小代价

类似的,rf[i][x][y]表示在左区间中从x点开始,经过了mid+1到i的边,最后走到了y的最小代价。

那么我们将询问挂在l上,枚举i到mid,如果有询问的r在mid+1到r上,

则对于询问\(<u,v,l,r>\)

枚举中转点z,\(ans=min\{lf[l][u][z]+rf[r]][z][v]\}\)

至于更新lf和rf

如果当前区间为左区间,

我们可以直接dp求出每条边到r的最小代价,

对于由区间

则求出从l到每条边的最小代价。

那么总时间复杂度为\(O(qn(对于每个询问枚举中转点求答案)+qlogm(查看挂在每个点的询问)+n^2mlogm(更新lf和rf))\)

#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
#include <map>
const int maxlongint=2147483647;
const int mo=1e9+7;
const int N=200005;
using namespace std;
struct lzh
{
int x,y,l,r;
}qu[N*2],b[N*2];
int n,m,q,next[N*2],last[N*2];
long long f[20005][33][33],ans[N];
long long min(long long x,long long y)
{
return x<y?x:y;
}
void dg(int l,int r,int t)
{
int mid=(l+r)>>1;
if(l!=r) dg(l,mid,0),dg(mid+1,r,1);
for(int x=l;x<=mid;x++)
{
for(int i=last[x];i;i=next[i])
{
if(qu[i].r>mid && qu[i].r<=r)
{
for(int y=1;y<=n;y++) ans[i]=min(ans[i],f[qu[i].l][qu[i].x][y]+f[qu[i].r][y][qu[i].y]);
}
}
}
if(t==2) return;
for(int i=l;i<=r;i++) memset(f[i],60,sizeof(f[i]));
if(!t)
{
for(int x=1;x<=n;x++)
{
f[r][x][x]=b[r].r;
if(b[r].x==x) f[r][b[r].y][x]=min(f[r][b[r].y][x],b[r].l);
if(b[r].y==x) f[r][b[r].x][x]=min(f[r][b[r].x][x],b[r].l);
for(int i=r-1;i>=l;i--)
{
for(int y=1;y<=n;y++) f[i][y][x]=f[i+1][y][x]+b[i].r;
int xx=b[i].x,yy=b[i].y;
f[i][yy][x]=min(f[i][yy][x],f[i+1][xx][x]+b[i].l);
f[i][xx][x]=min(f[i][xx][x],f[i+1][yy][x]+b[i].l);
}
}
}
else
{
for(int x=1;x<=n;x++)
{
f[l][x][x]=b[l].r;
if(b[l].x==x) f[l][x][b[l].y]=min(f[l][x][b[l].y],b[l].l);
if(b[l].y==x) f[l][x][b[l].x]=min(f[l][x][b[l].x],b[l].l);
for(int i=l+1;i<=r;i++)
{
for(int y=1;y<=n;y++) f[i][x][y]=f[i-1][x][y]+b[i].r;
int xx=b[i].x,yy=b[i].y;
f[i][x][yy]=min(f[i][x][yy],f[i-1][x][xx]+b[i].l);
f[i][x][xx]=min(f[i][x][xx],f[i-1][x][yy]+b[i].l);
}
}
}
}
int main()
{
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=m;i++) scanf("%d%d%d%d",&b[i].x,&b[i].y,&b[i].l,&b[i].r);
int sum[n+2],sum1[n+2];
memset(f,60,sizeof(f));
memset(ans,60,sizeof(ans));
for(int i=1,x,y,l,r;i<=q;i++)
{
scanf("%d%d%d%d",&qu[i].x,&qu[i].y,&qu[i].l,&qu[i].r);
if(qu[i].l==qu[i].r)
{
if(qu[i].x==qu[i].y) ans[i]=b[qu[i].l].r;
if(qu[i].x==b[qu[i].l].x && qu[i].y==b[qu[i].l].y || qu[i].x==b[qu[i].l].y && qu[i].y==b[qu[i].l].x) ans[i]=min(ans[i],b[qu[i].l].l);
continue;
}
next[i]=last[qu[i].l],last[qu[i].l]=i;
}
dg(1,m,2);
for(int i=1;i<=q;i++)
{
if(ans[i]>=f[0][0][0]) printf("-1\n");
else printf("%lld\n",ans[i]);
}
}

【JZOJ5430】【NOIP2017提高A组集训10.27】图的更多相关文章

  1. 【JZOJ5428】【NOIP2017提高A组集训10.27】查询

    题目 给出一个长度为n的序列a[] 给出q组询问,每组询问形如\(<x,y>\),求a序列的所有区间中,数字x的出现次数与数字y的出现次数相同的区间有多少个. 分析 我们可以维护一个前缀和 ...

  2. 5433. 【NOIP2017提高A组集训10.28】图

    题目描述 Description 有一个n个点A+B条边的无向连通图,有一变量x,每条边的权值都是一个关于x的简单多项式,其中有A条边的权值是k+x,另外B条边的权值是k-x,如果只保留权值形如k+x ...

  3. 【JZOJ5439】【NOIP2017提高A组集训10.31】Calculate

    题目 分析 对于\[\sum_{i=1}^{n}\lfloor\dfrac{T-B_i}{A_i}\rfloor\] 我们考虑拆开处理,得到 \[\sum_{i=1}^{n}(\lfloor\dfra ...

  4. 5432. 【NOIP2017提高A组集训10.28】三元组

    题目 题目大意 给你\(X+Y+Z\)个三元组\((x_i,y_i,z_i)\). 然后选\(X\)个\(x_i\),选\(Y\)个\(y_i\),选\(Z\)个\(z_i\). 每个三元组只能选择其 ...

  5. [JZOJ 5437] [NOIP2017提高A组集训10.31] Sequence 解题报告 (KMP)

    题目链接: http://172.16.0.132/senior/#main/show/5437 题目: 题解: 发现满足上述性质并且仅当A序列的子序列的差分序列与B序列的差分序列相同 于是我们把A变 ...

  6. 【JZOJ5434】【NOIP2017提高A组集训10.30】Matrix

    题目 分析 假设答案为ans, 发现\[k=\sum_{i=1}^{min(n,k)}\lfloor \dfrac{ans}{i} \rfloor\] 于是可以对ans进行二分, 用分块来求出上面的式 ...

  7. 【NOIP2017提高A组集训10.21】Fantasy

    题目 Y sera 陷入了沉睡,幻境中它梦到一个长度为N 的序列{Ai}. 对于这个序列的每一个子串,定义其幻境值为这个子串的和,现在Y sera 希望选择K 个不同的子串并使得这K 个子串的幻境值之 ...

  8. NOIP2017提高A组模拟10.6】Biology

    题目 trie 暴力就是对于每个询问的T个字符串 第i个和第i+1个直接个从后暴力枚举每位是否相同, 但这个方法TLE 我们考虑是否可以用更快的方法来求出两个字符串的最长公共后缀. 我们把所有的字符串 ...

  9. 【NOIP2017提高A组模拟10.7】Adore

    题目 小w 偶然间见到了一个DAG. 这个DAG 有m 层,第一层只有一个源点,最后一层只有一个汇点,剩下的每一层都有k 个节点. 现在小w 每次可以取反第i(1 < i < n - 1) ...

随机推荐

  1. 【VS开发】CTimeSpan类

    CTimeSpan类.        日期和时间类简介        CTime类的对象表示的时间是基于格林威治标准时间(GMT)的.CTimeSpan类的对象表示的是时间间隔.        CTi ...

  2. (转)Jquery+Ajax实现Select动态定数据

    解决思路: 在数据库中建立类型字典式表.将下拉框需要添加的项,在数据库表里中文.英文名称对应起来. 下拉框动态绑定数据库表中需要字段. <div id="bgDiv" sty ...

  3. nginx加php(一)

    yum install nginx 安装php7.3https://kifarunix.com/installing-php-7-3-3-on-centos-7-6/ yum install epel ...

  4. vim配置及插件安装笔记

    1. 首先打开vim的配置文件vimrc,并加入以下常用的配置: cd ~ mkdir .vim vim .vimrc " 设置当文件被改动时自动载入 set autoread " ...

  5. (5.7)mysql高可用系列——MySQL中的GTID复制(理论篇)【转】

    转自:https://blog.csdn.net/wmq880204/article/details/53160078 一.GTID的概述: 1.全局事物标识:global transaction i ...

  6. codeforces 816B Karen and Coffee (差分思想)

    题目链接 816B Karen and Coffee 题目分析 题意:有个人在学泡咖啡,因此看了很多关于泡咖啡温度的书,得到了n种推荐的泡咖啡温度范围[L1,R1] ,此人将有k种做法推荐的温度记为可 ...

  7. 正则爬取某段子网站前20页段子(request库)

    首先还是谷歌浏览器抓包对该网站数据进行分析,结果如下: 该网站地址:http://www.budejie.com/text 该网站数据都是通过html页面进行展示,网站url默认为第一页,http:/ ...

  8. php 如何生成path及其日常维护

    php 如何生成path及其日常维护 path字段重要性不言而喻,在查询的时候,如果只用pid,查询效率会很低,增加path,查询效率大大提高,最起码不用递归查库了,重点是维护推荐关系的时候要维护pa ...

  9. 2019年8月23日 星期五(workerman和swoole的区别)

    两个框架我都有用过,workerman用得更多些,这2个框架都很出名,它们的出现大大的提高了php的应用范围及知名度 workerman和swoole都是php socket 服务器框架,都支持长连接 ...

  10. Java小程序—录屏小程序(上半场)

    做软件的三个步骤: (1)做什么? (2)怎么做? (3)动手做! ok,我们今天要做的是一个录屏软件,那怎么做呢?首先,我们小时候都玩过一种小人书,就是当你快速翻动书页时,书中的人物就会活灵活现的动 ...