P5530 [BalticOI 2002]双调路径

输入样例:
4 5 1 4
2 1 2 1
3 4 3 1
2 3 1 2
3 1 1 4
2 4 2 4

样例如下图

样例说明:

从1到4有4条路径。为1→2→4(费用为4,时间为5) ,1→3→4(费用为4,时间为5) ,1→2→3→4(费用为6,时间为4) ,1→3→2→4(费用为4,时间为10)。 1→3→4和1→2→4比1→3→2→4更好。有两种最佳路径:费用为4 ,时间为5(1→2→4和1→3→4)和费用为6,时间为4 (1→2→3→4)。

分析

最短路的边有两种权值,所以考虑在每个节点增加一维状态,d【i】【j】:到达节点i且费用为j时所用最少时间,则d【v】【j】=min{d【u】【j-cost(u,v)】}+time(u,v)

用SPFA即可, 533ms / 6.12MB,#8#9TLE,86分

#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
#define R register
struct edge {
int v,w,t,h;
} e[610];
int h[110],d[110][10100],cnt,mn;
int u,v,w,n,m,S,T;
bool vis[110][10100];//第二维记得开大一些 inline void add(int u,int v,int w,int t) {
e[++cnt]=(edge) {v,w,t,h[u]},h[u]=cnt;
} queue<pair<int,int> >q;//二维记录节点u和所用cost
inline void spfa() {
memset(d,0x3f,sizeof d);
mn=99999999;
q.push(make_pair(S,d[S][0]=0)),vis[S][0]=1;
while(!q.empty()) {
u=q.front().first,w=q.front().second;
vis[u][w]=0,q.pop();
for (R int i=h[u],_w; i; i=e[i].h)
if ((_w=w+e[i].w)<=10010) {//w是到达u的cost,_w是由u到达v所用cost,_w超出100*100直接舍去
if (d[v=e[i].v][_w]>d[u][w]+e[i].t) {//同样的cost所用time是否比原来更少
d[v][_w]=d[u][w]+e[i].t;
if(!vis[v][_w]) q.push(make_pair(v,_w)),vis[v][_w]=1;
}
}
}
} int main() {
scanf("%d%d%d%d",&n,&m,&S,&T);
for (R int t; m; m--)
scanf("%d%d%d%d",&u,&v,&w,&t),add(u,v,w,t),add(v,u,w,t);
spfa(); cnt=0;
for (R int i=0; i<=10000; i++)
if(d[T][i]<mn) mn=d[T][i],cnt++;//cost逐渐增长,那么time只有小于其他的time才能算“最小路径”
printf("%d",cnt);
}

优化

不难想到,对于d【i】【j】,如果有k(k<j)且d【i】【k】<d【i】【j】(到达i所用cost和time都更少),那么d【i】【j】也就没必要更新了。所以加入剪枝:用树状数组维护d【i】【0~j】的最小值,只有d【i】【j】<最小值才更新

实际效率提高不少, 93ms / 9.93MB,AC代码:

#include<cstdio>
#include<queue>
#include<cstring>
#include<iostream>
using namespace std;
#define R register
struct edge {
int v,w,t,h;
} e[610];
int h[110],d[110][10100],tr[110][10100],cnt,mn;
int u,v,w,n,m,S,T;
bool vis[110][10100]; inline void add(int u,int v,int w,int t) {
e[++cnt]=(edge) {v,w,t,h[u]},h[u]=cnt;
} //用val更新d【x】【0~y】最小值
inline void upd(int x,int y,int val){
for (y++;y<10100;y+=y&-y) tr[x][y]=min(tr[x][y],val);
}//树状数组下标不能为0,所以y++ //查询d【x】【0~y】最小值
inline int qry(int x,int y){
int ans=1e7;
for (y++;y;y-=y&-y) ans=min(tr[x][y],ans);
return ans;
} queue<pair<int,int> >q;
inline void spfa() {
memset(d,0x3f,sizeof d);
memset(tr,0x3f,sizeof d);//别忘了初始化
q.push(make_pair(S,d[S][0]=0)),vis[S][0]=1;
upd(S,0,0);
while(!q.empty()) {
u=q.front().first,w=q.front().second;
vis[u][w]=0,q.pop();
for (R int i=h[u],_w; i; i=e[i].h)
if (qry(v=e[i].v,_w=w+e[i].w)>d[u][w]+e[i].t) {//只有d【i】【j】<最小值才更新
d[v][_w]=d[u][w]+e[i].t;
upd(v,_w,d[v][_w]);//更新最小值
if(!vis[v][_w]) q.push(make_pair(v,_w)),vis[v][_w]=1;
}
}
} int main() {
scanf("%d%d%d%d",&n,&m,&S,&T);
for (R int t; m; m--)
scanf("%d%d%d%d",&u,&v,&w,&t),add(u,v,w,t),add(v,u,w,t);
spfa(); cnt=0,mn=99999999;
for (R int i=0; i<=10000; i++)
if(d[T][i]<mn) mn=d[T][i],cnt++;
printf("%d",cnt);
}

题解 P5530 [BalticOI 2002]双调路径的更多相关文章

  1. P5530 [BOI 2002]双调路径

    题意描述 [BOI 2002]双调路径 题意描述的确实不是很清楚(出题人惜字如金). 给定一张有 \(n\) 个点,\(m\) 条边的无向图,每条边有两个权值,分别表示经过这个点的代价和时间. 同时给 ...

  2. Bicriterial routing 双调路径 HYSBZ - 1375(分层最短路)

    Description 来越多,因此选择最佳路径是很现实的问题.城市的道路是双向的,每条道路有固定的旅行时间以及需要支付的费用.路径由连续的道路组成.总时间是各条道路旅行时间的和,总费用是各条道路所支 ...

  3. bzoj1375 双调路径

    Description 来越多,因此选择最佳路径是很现实的问题.城市的道路是双向的,每条道路有固定的旅行时间以及需要支付的费用.路径由连续的道路组成.总时间是各条道路旅行时间的和,总费用是各条道路所支 ...

  4. 【题解】最长递增路径 [51nod1274]

    [题解]最长递增路径 [51nod1274] 传送门:最长递增路径 \([51nod1274]\) [题目描述] 一个可能有自环有重边的无向图,每条边都有边权.输入两个整数 \(n,m\) 表示一共 ...

  5. [bzoj1375] [Baltic2002] Bicriterial routing 双调路径

    Description 如今的道路收费发展很快.道路的密度越来越大,因此选择最佳路径是很现实的问题.城市的道路是双向的,每条道路有固定的旅行时间以及需要支付的费用. 路径是连续经过的道路组成的.总时间 ...

  6. 题解-[WC2011]最大XOR和路径

    [WC2011]最大XOR和路径 给一个 \(n\) 个点 \(m\) 条边(权值为 \(d_i\))的无向有权图,可能有重边和子环.可以多次经过一条边,求 \(1\to n\) 的路径的最大边权异或 ...

  7. PAT甲题题解-1003. Emergency (25)-最短路径+路径数目

    给出n个城市,m条边,起始点c1和目的点c2接下来给出n个城市的队伍数以及m条双向边问你求c1到c2的所有最短路径数目,以及其中经过的最多队伍数 先最短路dijkstra,同时建立vector数组pr ...

  8. 题解 [51nod1274] 最长递增路径

    题面 解析 这题一眼DP啊. 然而想了半天毫无思路. 后来看题解后发现可以按边权的大小顺序DP. 将边权从小到大排序,对于权值相同的边分为一组. 设\(f[i][0]\)表示经过当前权值的边后到达\( ...

  9. 【题解】[BalticOI 2014]friends

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3916 (BZOJ3916) 由题意可知 \(N\) 得为奇数,\(S\) 才存在,所以先特 ...

随机推荐

  1. Web简单小结

    一.HTML DOM 使 JavaScript 有能力对 HTML 事件做出反应:<h1 onclick="this.innerHTML='你点我干啥'">请点击这里& ...

  2. unity踩坑2020-01-21

    这几天一直在测试一个类似于传奇的2d界面游戏,目前做的测试为: 人物动作响应,主要是8方向的判断和资源文件精灵的刷新. 学到的知识点: 1,Enum.GetHashCode() 可以得到这个枚举的索引 ...

  3. ZedGraph怎样实现将图形右键菜单的打印和页面设置合并为打印的二级子菜单

    场景 Winforn中实现ZedGraph自定义添加右键菜单项(附源码下载): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/10 ...

  4. 2018 HBCPC 菜鸡选手记

    我果然太菜了 A B--T2 D--T4 C--T3 F 我果然太菜了 作为学校最菜的队员,今天下午被虐惨了. 一下午才做A-D四道题 官方题解链接 晚上吃完饭再去看. A 队友A的不清楚.没看题. ...

  5. 0002 PyCharm设置

    1 设置编码格式 File/Settings/Editor/File Encodings 2 设置字体 File/Settings/Editor/Font 3 鼠标滚轮改变编辑器字体大小 File/S ...

  6. 2019ICPC南昌站E.Bob's Problem

    题意: 一张图,n个点,m条边分为黑边和白边,黑边任意选,白边只能选k条,在保持整张图连通的情况下使得所选变的权值和最大 解析: 因为边权全部是正值,所以可以把黑边全选上,缩点之后对各个连通块和白边进 ...

  7. HDU-1506 Largest Rectangle in a Histogram【单调栈】

    Description A histogram is a polygon composed of a sequence of rectangles aligned at a common base l ...

  8. ASP.NET MVC简单流程解释(传值方式)

    在上篇笔记里我们创建了一个简单的MVC程序 在view中,@Model指的就是MyFirstMvc.Models.IndexModel,我们的提交页面是/Test/Index,当我们输入完数字并按下提 ...

  9. HTTPClient模拟Get和Post请求

    一.模拟Get请求(无参) 首先导入HttpClient依赖 <dependency> <groupId>org.apache.httpcomponents</group ...

  10. 4817 [Sdoi2017]树点涂色

    题目描述 Bob 有一棵 n 个点的有根树,其中 1 号点是根节点.Bob 在每个点上涂了颜色,并且每个点上的颜色不同. 定义一条路径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色. ...