1. 程式人生 > >505. 城市(二分答案)

505. 城市(二分答案)

正整數 tin dijkstra 格式 def 優化 nbsp urn 一行

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,二分答案。堆優化

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<queue>
 5 using namespace std;
 6 const int MAXN = 10100 ;
 7 struct Edge{
 8     int to,w,nxt;
 9 }e[100010];
10 struct Node{
11     int node,dist;
12     bool operator < (const Node& a) const
13     {
14         return dist > a.dist;
15     }
16 }k;
17 int c[MAXN],head[MAXN],dis[MAXN];
18 bool vis[MAXN];
19 int st,en,s,cnt,n,m;
20 priority_queue<Node>q;
21 void add(int u,int v,int w)
22 {
23     ++cnt;
24     e[cnt].to = v;
25     e[cnt].w = w;
26     e[cnt].nxt = head[u];
27     head[u] = cnt; 
28 } 
29 bool ok(int x)
30 {
31     if (c[st]>x||c[en]>x) return false;
32     memset(dis,0x3f,sizeof(dis));
33     memset(vis,false,sizeof(vis));
34     dis[st] = 0;
35     vis[st] = true;
36     q.push((Node){st,dis[st]});
37     while (!q.empty())
38     {
39         k = q.top();
40         q.pop();
41         int u = k.node;
42         vis[u] = false;
43         for (int i=head[u]; i; i=e[i].nxt)
44         {
45             int v = e[i].to, w = e[i].w;
46             if (c[v]>x) continue ;
47             if (dis[v]>dis[u]+w)
48             {
49                 dis[v] = dis[u]+w;
50                 if (!vis[v])
51                 {
52                     q.push((Node){v,dis[v]});
53                     vis[v] = true;
54                 }
55             }
56         }
57     }
58     if (dis[en] > s) return false ;
59     return true ;
60 }
61 int main()
62 {
63     freopen("cost.in","r",stdin);
64     freopen("cost.out","w",stdout);
65     int l=1e9,r=0;
66     scanf("%d%d%d%d%d",&n,&m,&st,&en,&s);
67     for (int i=1; i<=n; ++i)
68     {
69         scanf("%d",&c[i]);
70         r = max(c[i],r);
71         l = min(c[i],l); 
72     }
73     for (int x,y,z,i=1; i<=m; ++i)
74     {
75         scanf("%d%d%d",&x,&y,&z);
76         add(x,y,z);
77         add(y,x,z);
78     }
79     if (!ok(r))
80     {
81         printf("-1");
82         return 0;
83     }
84     while (l<=r)
85     {
86         int mid = (l+r)>>1;
87         if (ok(mid)) r = mid-1;
88         else l = mid+1;
89     }
90     printf("%d",r+1);
91     return 0;
92 }

70分spfa代碼,首先想的是spfa,單3個點超時

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<queue> 
 5 using namespace std;
 6 const int MAXN = 10100 ;
 7 struct Edge{
 8     int to,w,nxt;
 9 }e[50010];
10 int c[MAXN],head[MAXN],dis[MAXN];
11 bool vis[MAXN];
12 int st,en,s,cnt,n,m;
13  
14 void add(int u,int v,int w)
15 {
16     ++cnt;
17     e[cnt].to = v;
18     e[cnt].w = w;
19     e[cnt].nxt = head[u];
20     head[u] = cnt; 
21 } 
22 bool ok(int x)
23 {
24     if (c[st]>x) return false;
25     memset(dis,0x3f,sizeof(dis));
26     memset(vis,0,sizeof(vis));
27     queue<int>q;
28     q.push(st);
29     dis[st] = 0;
30     vis[st] = true;
31     while (!q.empty())
32     {
33         int u = q.front();
34         q.pop();
35         for (int i=head[u]; i; i=e[i].nxt)
36         {
37             int v = e[i].to;
38             int w = e[i].w;
39             if (c[v]>x) continue ;
40             if (dis[v]>dis[u]+w)
41             {
42                 dis[v] = dis[u]+w;
43                 if (!vis[v])
44                 {
45                     q.push(v);
46                     vis[v] = true;
47                 }
48             }
49         }
50         vis[u] = false;
51     }
52     if (dis[en] > s) return false ;
53     return true ;
54 }
55 int main()
56 {
57     freopen("cost.in","r",stdin);
58     freopen("cost.out","w",stdout);
59     int l=1e9,r;
60     scanf("%d%d%d%d%d",&n,&m,&st,&en,&s);
61     for (int i=1; i<=n; ++i)
62     {
63         scanf("%d",&c[i]);
64         r = max(c[i],r);
65         l = min(c[i],l); 
66     }
67     for (int x,y,z,i=1; i<=m; ++i)
68     {
69         scanf("%d%d%d",&x,&y,&z);
70         add(x,y,z);
71         add(y,x,z);
72     }
73     if (!ok(r))
74     {
75         printf("-1");
76         return 0;
77     }
78     while (l<=r)
79     {
80         int mid = (l+r)>>1;
81         if (ok(mid)) r = mid-1;
82         else l = mid+1;
83     }
84     printf("%d",r+1);
85     return 0;
86 }

505. 城市(二分答案)