首页 > 代码库 > 收费站(二分+最短路)

收费站(二分+最短路)

【题目描述】

    在某个遥远的国家里,有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,可能有两条边连接着相同的城市。

 

 

对每个城市的收费从小到大排序,进行二分答案

对于一个城市的收费,如果大于二分出的答案,则这个城市不能通过

每次二分求一次从起点到终点消耗汽油的最小值

如果大于容量,则不可行,反之可行

 

 

技术分享
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<queue>
 5 #include<algorithm>
 6 #define MAXN 10005
 7 #define MAXE 100005
 8 using namespace std;
 9 inline int read()
10 {
11     int x=0,f=1;
12     char ch=getchar();
13     while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}
14     while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}
15     return x*f;
16 }
17 typedef pair<int,int>pli;
18 struct Edge
19 {
20     int u,v,w;
21     int next;
22 }e[MAXE];
23 int head[MAXN],cnt=0,n,m,s,t,sum,cost[MAXN],costs[MAXN],dis[MAXN];
24 bool vis[MAXN];
25 inline void addedge(int u,int v,int w)
26 {
27     cnt++;
28     e[cnt].u=u;
29     e[cnt].v=v;
30     e[cnt].w=w;
31     e[cnt].next=head[u];
32     head[u]=cnt;
33 }
34 inline bool spfa(int val)
35 {
36     memset(dis,63,sizeof(dis));
37     deque<int>q;
38     q.push_back(s);dis[s]=0;vis[s]=1;
39     if(cost[s]>val) return 0;
40     while(!q.empty())
41     {
42         int u=q.front(); 
43         q.pop_front();vis[u]=0;
44         for(int i=head[u];i!=0;i=e[i].next)
45             if(dis[e[i].v]>dis[u]+e[i].w&&cost[e[i].v]<=val)
46             {
47                 dis[e[i].v]=dis[u]+e[i].w;
48                 if(!vis[e[i].v])
49                 {
50                     vis[e[i].v]=1;
51                     if(!q.empty())
52                     {
53                         if(dis[e[i].v]<dis[q.front()])
54                             q.push_front(e[i].v);
55                         else q.push_back(e[i].v);
56                     }
57                     else q.push_back(e[i].v);
58                 }
59             }
60     }
61     if(dis[t]>sum) return 0;
62     else return 1;
63 }
64 int main()
65 {
66     //freopen("cost.in","r",stdin);
67     //freopen("cost.out","w",stdout);
68     n=read(),m=read(),s=read(),t=read(),sum=read();
69     for(int i=1;i<=n;i++) costs[i]=cost[i]=read();
70     sort(costs+1,costs+n+1);
71     for(int i=1,u,v,w;i<=m;i++)
72     {
73         u=read(),v=read(),w=read();
74         addedge(u,v,w);
75         addedge(v,u,w);
76     }
77     int l=1,r=n,ans;
78     bool flag=0;
79     while(l<=r)
80     {
81         int mid=(l+r)>>1;
82         if(spfa(costs[mid]))
83         {
84             flag=1;
85             ans=mid;
86             r=mid-1;
87         }
88         else l=mid+1;
89     }
90     if(!flag) printf("-1");
91     else printf("%d",costs[ans]);
92 }
View Code

 

收费站(二分+最短路)