【BZOJ 1375】 [Baltic2002]Bicriterial routing 双调路径
2015-02-16 11:29
183 查看
1375: [Baltic2002]Bicriterial routing 双调路径
Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 299 Solved: 115
[Submit][Status]
Description
来越多,因此选择最佳路径是很现实的问题。城市的道路是双向的,每条道路有固定的旅行时间以及需要支付的费用。路径由连续的道路组成。总时间是各条道路旅行时间的和,总费用是各条道路所支付费用的总和。同样的出发地和目的地,如果路径A比路径B所需时间少且费用低,那么我们说路径A比路径B好。对于某条路径,如果没有其他路径比它好,那么该路径被称为最优双调路径。这样的路径可能不止一条,或者说根本不存在。 给出城市交通网的描述信息,起始点和终点城市,求最优双条路径的条数。城市不超过100个,边数不超过300,每条边上的费用和时间都不超过100。Input
第一行给出有多少个点,多少条边,开始点及结束点. 下面的数据用于描述这个地图Output
有多少条最优双调路径Sample Input
4 5 1 42 1 2 1
3 4 3 1
2 3 1 2
3 1 1 4
2 4 2 4
Sample Output
2HINT
分层图上的最短路。
f[i][j]表示走到i结点,费用为j的最少时间,直接跑spfa即可。
#include <iostream> #include <algorithm> #include <cstring> #include <cstdio> #include <cstdlib> #include <queue> #define inf 0x3f3f3f3f #define maxc (n-1)*100 using namespace std; struct edge { int y,ne,c,t; }e[1000]; struct now { int p,c; }; int tot=0,n,m; struct data { int t,f; }d[105][10005]; int s,t,h[105],inq[105][10005]; void Addedge(int x,int y,int co,int ti) { tot++; e[tot].y=y; e[tot].ne=h[x]; h[x]=tot; e[tot].c=co; e[tot].t=ti; } void spfa() { for (int i=1;i<=n;i++) for (int j=0;j<=maxc;j++) d[i][j].f=0,inq[i][j]=0,d[i][j].t=inf; queue<now> q; now x; x.p=s,x.c=0; d[s][0].f=1,d[s][0].t=0; inq[s][0]=1; q.push(x); while (!q.empty()) { x=q.front(); q.pop(); inq[x.p][x.c]=0; for (int i=h[x.p];i;i=e[i].ne) { int y=e[i].y; int co=e[i].c+x.c; if (co>maxc) continue; if (d[y][co].t>d[x.p][x.c].t+e[i].t) { d[y][co].t=d[x.p][x.c].t+e[i].t; d[y][co].f=1; if (!inq[y][co]) { now aa; aa.p=y,aa.c=co; q.push(aa),inq[y][co]=1; } } } } } int main() { scanf("%d%d%d%d",&n,&m,&s,&t); for (int i=1;i<=m;i++) { int x,y,ti,co; scanf("%d%d%d%d",&x,&y,&co,&ti); Addedge(x,y,co,ti); Addedge(y,x,co,ti); } spfa(); int ans=0,minn=maxc+10; for (int i=0;i<=maxc;i++) { if (!d[t][i].f) continue; if (d[t][i].t>=minn) continue; minn=d[t][i].t; ans++; } cout<<ans<<endl; return 0; }
wa是因为求答案时写了break,应该是continue。
其实这个题还可以进行优化:
如果存在f[i][k],满足k<j且f[i][k]<f[i][j],那么f[i][j]一定不是最优解。
因此我们可以给每一个结点建一棵线段树,维护最小值即可。
#include <iostream> #include <algorithm> #include <cstring> #include <cstdio> #include <cstdlib> #include <queue> #define inf 0x3f3f3f3f #define maxc (n-1)*100+5 using namespace std; struct edge { int y,ne,c,t; }e[1000]; struct now { int p,c; }; int tot=0,n,m; struct data { int t,f; }d[105][10005]; int s,t,h[105],inq[105][10005]; struct segtree { int l,r,minn; }T[105][40005]; void Addedge(int x,int y,int co,int ti) { tot++; e[tot].y=y; e[tot].ne=h[x]; h[x]=tot; e[tot].c=co; e[tot].t=ti; } void Build(int now,int x,int l,int r) { T[now][x].l=l,T[now][x].r=r; if (l==r) { T[now][x].minn=maxc; return; } int m=(l+r)>>1; Build(now,x<<1,l,m); Build(now,(x<<1)+1,m+1,r); T[now][x].minn=maxc; } void Update(int now,int x,int p,int k) { if (T[now][x].l==T[now][x].r&&T[now][x].l==p) { T[now][x].minn=min(k,T[now][x].minn); return; } int m=(T[now][x].l+T[now][x].r)>>1; if (p<=m) Update(now,x<<1,p,k); else Update(now,(x<<1)+1,p,k); T[now][x].minn=min(T[now][x<<1].minn,T[now][(x<<1)+1].minn); } int Get(int now,int x,int l,int r) { if (T[now][x].l>=l&&T[now][x].r<=r) return T[now][x].minn; int m=(T[now][x].l+T[now][x].r)>>1; if (r<=m) return Get(now,x<<1,l,r); if (l>m+1) return Get(now,(x<<1)+1,l,r); return min(Get(now,x<<1,l,r),Get(now,(x<<1)+1,l,r)); } void spfa() { for (int i=1;i<=n;i++) for (int j=0;j<=maxc;j++) d[i][j].f=0,inq[i][j]=0,d[i][j].t=inf; queue<now> q; now x; x.p=s,x.c=0; d[s][0].f=1,d[s][0].t=0; inq[s][0]=1; Update(s,1,0,0); q.push(x); while (!q.empty()) { x=q.front(); q.pop(); inq[x.p][x.c]=0; for (int i=h[x.p];i;i=e[i].ne) { int y=e[i].y; int co=e[i].c+x.c; if (co>maxc) continue; if (d[y][co].t>d[x.p][x.c].t+e[i].t&&Get(y,1,0,co)>d[x.p][x.c].t+e[i].t) { d[y][co].t=d[x.p][x.c].t+e[i].t; d[y][co].f=1; Update(y,1,co,d[y][co].t); if (!inq[y][co]) { now aa; aa.p=y,aa.c=co; q.push(aa),inq[y][co]=1; } } } } } int main() { scanf("%d%d%d%d",&n,&m,&s,&t); for (int i=1;i<=m;i++) { int x,y,ti,co; scanf("%d%d%d%d",&x,&y,&co,&ti); Addedge(x,y,co,ti); Addedge(y,x,co,ti); } for (int i=1;i<=n;i++) Build(i,1,0,maxc); spfa(); int ans=0,minn=maxc+10; for (int i=0;i<=maxc;i++) { if (!d[t][i].f) continue; if (d[t][i].t>=minn) continue; minn=d[t][i].t; ans++; } cout<<ans<<endl; return 0; }
进入第一版~
其实没必要用线段树,因为是求前缀的最小值,直接树状数组就可以了。。
相关文章推荐
- BZOJ 1375 [Baltic2002]Bicriterial routing 双调路径 SPFA
- bzoj1375[Baltic2002]Bicriterial routing 双调路径
- bzoj1375 [Baltic2002]Bicriterial routing 双调路径 (两个值的最短路)
- BZOJ 1375: [Baltic2002]Bicriterial routing 双调路径 SPFA+DP思想
- BZOJ 1375 Bicriterial routing 双调路径 (二维最短路)
- bzoj1375 双调路径
- [BalticOI2002]Bicriterial routing
- BZOJ 2150 浅谈二分图Bipartite Graph及DAG最小路径覆盖
- 【最小路径覆盖】【二分图】【最大流】【Dinic】bzoj2150 部落战争
- BZOJ2002 [Hnoi2010]Bounce 弹飞绵羊
- bzoj2002 [Hnoi2010]Bounce 弹飞绵羊 (LCT)
- 【BZOJ3627】【JLOI2014】路径规划 分层图
- Bzoj 1588: [HNOI2002]营业额统计(splay)
- [BZOJ2002][HNOI2010]-弹飞绵羊-LCT
- [Bzoj1355][Baltic2009]Radio Transmission(KMP)
- BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊
- [BFS 剪枝] BZOJ 2954 [Poi2002]超级马
- 双调路径
- [BZOJ1588][HNOI2002]营业额统计
- [BZOJ2337][HNOI2011]XOR和路径(高斯消元解期望方程)