505. 城市(二分答案)
505. 城市
★★ 输入文件:cost.in
输出文件:cost.out
简单对比
时间限制:1 s 内存限制:128 MB
【题目描述】
在某个遥远的国家里,有n个城市。编号为1,2,3,……,n。
这个国家的政府修建了m条双向的公路。每条公路连接着两个城市。沿着某条公路,开车从一个城市到另一个城市,需要花费一定的汽油。
开车每经过一个城市,都会被收取一定的费用(包括起点和终点城市)。所有的收费站都在城市中,在城市间的公路上没有任何的收费站。
小红现在要开车从城市u到城市v(1<=u,v<=n)。她的车最多可以装下s升的汽油。在出发的时候,车的油箱是满的,并且她在路上不想加油。
在路上,每经过一个城市,她要交一定的费用。如果她某次交的费用比较多,她的心情就会变得很糟。所以她想知道,在她能到达目的地的前提下,她交的费用中最多的一次最少是多少。这个问题对于她来说太难了,于是她找到了聪明的你,你能帮帮她吗?
【输入格式】
第一行5个正整数,n,m,u,v,s。分别表示有n个城市,m条公路,从城市u到城市v,车的油箱的容量为s升。
接下来有n行,每行1个正整数,fi。表示经过城市i,需要交费fi元。
再接下来有m行,每行3个正整数,ai,bi,ci(1<=ai,bi<=n)。表示城市ai和城市bi之间有一条公路,如果从城市ai到城市bi,或者从城市bi到城市ai,需要用ci升汽油。
【输出格式】
仅一个整数,表示小红交费最多的一次的最小值。
如果她无法到达城市v,输出-1。
【输入样例1】
4 4 2 3 8 8 5 6 10 2 1 2 2 4 1 1 3 4 3 4 3
- 【输出样例1】
8
- 【输入样例2】
4 4 2 3 3 8 5 6 10 2 1 2 2 4 1 1 3 4 3 4 3
- 【输出样例2】
-1
- 【数据规模】
对于60%的数据,满足n<=200,m<=10000,s<=200
对于100%的数据,满足n<=10000,m<=50000,s<=1000000000
对于100%的数据,满足ci<=1000000000,fi<=1000000000,可能有两条边连接着相同的城市。
dijkstra,二分答案。堆优化
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; const int MAXN = 10100 ; struct Edge{ int to,w,nxt; }e[100010]; struct Node{ int node,dist; bool operator < (const Node& a) const { return dist > a.dist; } }k; int c[MAXN],head[MAXN],dis[MAXN]; bool vis[MAXN]; int st,en,s,cnt,n,m; priority_queue<Node>q; void add(int u,int v,int w) { ++cnt; e[cnt].to = v; e[cnt].w = w; e[cnt].nxt = head[u]; head[u] = cnt; } bool ok(int x) { if (c[st]>x||c[en]>x) return false; memset(dis,0x3f,sizeof(dis)); memset(vis,false,sizeof(vis)); dis[st] = 0; vis[st] = true; q.push((Node){st,dis[st]}); while (!q.empty()) { k = q.top(); q.pop(); int u = k.node; vis[u] = false; for (int i=head[u]; i; i=e[i].nxt) { int v = e[i].to, w = e[i].w; if (c[v]>x) continue ; if (dis[v]>dis[u]+w) { dis[v] = dis[u]+w; if (!vis[v]) { q.push((Node){v,dis[v]}); vis[v] = true; } } } } if (dis[en] > s) return false ; return true ; } int main() { freopen("cost.in","r",stdin); freopen("cost.out","w",stdout); int l=1e9,r=0; scanf("%d%d%d%d%d",&n,&m,&st,&en,&s); for (int i=1; i<=n; ++i) { scanf("%d",&c[i]); r = max(c[i],r); l = min(c[i],l); } for (int x,y,z,i=1; i<=m; ++i) { scanf("%d%d%d",&x,&y,&z); add(x,y,z); add(y,x,z); } if (!ok(r)) { printf("-1"); return 0; } while (l<=r) { int mid = (l+r)>>1; if (ok(mid)) r = mid-1; else l = mid+1; } printf("%d",r+1); return 0; }
70分spfa代码,首先想的是spfa,单3个点超时
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; const int MAXN = 10100 ; struct Edge{ int to,w,nxt; }e[50010]; int c[MAXN],head[MAXN],dis[MAXN]; bool vis[MAXN]; int st,en,s,cnt,n,m; void add(int u,int v,int w) { ++cnt; e[cnt].to = v; e[cnt].w = w; e[cnt].nxt = head[u]; head[u] = cnt; } bool ok(int x) { if (c[st]>x) return false; memset(dis,0x3f,sizeof(dis)); memset(vis,0,sizeof(vis)); queue<int>q; q.push(st); dis[st] = 0; vis[st] = true; while (!q.empty()) { int u = q.front(); q.pop(); for (int i=head[u]; i; i=e[i].nxt) { int v = e[i].to; int w = e[i].w; if (c[v]>x) continue ; if (dis[v]>dis[u]+w) { dis[v] = dis[u]+w; if (!vis[v]) { q.push(v); vis[v] = true; } } } vis[u] = false; } if (dis[en] > s) return false ; return true ; } int main() { freopen("cost.in","r",stdin); freopen("cost.out","w",stdout); int l=1e9,r; scanf("%d%d%d%d%d",&n,&m,&st,&en,&s); for (int i=1; i<=n; ++i) { scanf("%d",&c[i]); r = max(c[i],r); l = min(c[i],l); } for (int x,y,z,i=1; i<=m; ++i) { scanf("%d%d%d",&x,&y,&z); add(x,y,z); add(y,x,z); } if (!ok(r)) { printf("-1"); return 0; } while (l<=r) { int mid = (l+r)>>1; if (ok(mid)) r = mid-1; else l = mid+1; } printf("%d",r+1); return 0; }
- hdu 2295 Radar 重复覆盖 DLX+二分答案 给出一些城市及一些雷达的坐标,要求从这些雷达中选取最多k个能够覆盖所有的城市,问雷达的最小覆盖半径为多少
- hdu 3656 Fire station 重复覆盖 DLX+二分答案 给出一些城市及一些救火站的坐标,要求这些救火站覆盖所有的城市,问从救火站到城市的最长时间至少是多少。
- BZOJ 3613 Heoi2014 南园满地堆轻絮 二分答案/线性做法
- HDOJ 3586 Information Disturbing(二分答案+树DP)
- BZOJ 1614: [Usaco2007 Jan]Telephone Lines架设电话线 二分答案 最短路
- k大子段和 二分答案 + 平衡树
- BZOJ 1044: [HAOI2008]木棍分割|动态规划|二分答案
- binary string codeforces 862D 交互题,二分答案
- UVa 10566 Crossed Ladders 平面几何结论,二分答案
- NKOJ 2650 (SDOI 2011) 消防(树的直径+DP+单调队列/二分答案)
- 【二分答案】【最大流】bzoj3130 [Sdoi2013]费用流
- codeforces #8D Two Friends (二分答案+计算几何)
- 1540: 第k大数 两个数组元素相乘后的第k大( 二分答案 + 输入输出优化 )
- bzoj 4476: [Jsoi2015]送礼物 二分答案+单调队列
- 【BZOJ1044】【tyvj3511】【codevs1870】木棍分割,二分答案+滚动数组+前缀和DP
- #1139 : 二分·二分答案
- pku2112 最大流,弗洛伊德,二分答案
- BZOJ 3007 解救小云公主 二分答案+对偶图
- BC 2015年百度之星程序设计大赛 - 初赛(1)(序列变换-二分答案贪心)
- [BZOJ2095]-[Poi2010]Bridges-二分答案+混合图欧拉回路判定