您的位置:首页 > 其它

505. 城市(二分答案)

2017-06-27 19:47 239 查看

 

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐