505. 城市(二分答案)
阿新 • • 發佈:2017-06-27
正整數 tin dijkstra 格式 def 優化 nbsp urn 一行 在路上,每經過一個城市,她要交一定的費用。如果她某次交的費用比較多,她的心情就會變得很糟。所以她想知道,在她能到達目的地的前提下,她交的費用中最多的一次最少是多少。這個問題對於她來說太難了,於是她找到了聰明的你,你能幫幫她嗎?
【輸入格式】
第一行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】
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. 城市(二分答案)