hihocoder 二分·二分答案【二分搜尋,最大化最小值】 (bfs)
阿新 • • 發佈:2019-02-19
這道題做了幾個小時了都沒有做出來,首先是題意搞了半天都沒有弄懂,難道真的是因為我不打遊戲所以連題都讀不懂了?
反正今天是弄不懂了,過幾天再來看看。。。
題意:一個人從1點出發到T點去打boss,這個人有兩個屬性值,防禦值和戰鬥值,這兩個值成反比,為了打贏boss我們要使戰鬥值最大,於是乎防禦值就要最低,但是也不能太低,於是乎這個界限在哪,這就是我們要求的。每條路上都有一個索敵值,防禦值必須>=索敵值 才能通過。從1點到T點有很多條通路,我們要找的是:這每一條通路中索敵值最大的中索敵值最小的,感覺這句話有點繞,具體解釋看下圖:
1號節點是起點,5號是終點,從1到5有三條通路:1->2->5; 1->3->5; 1->4->5; 對應路徑中最長的路段長度分別是:3;5;4;因此在{3,5,4}中最小值3是正確值。
所以這道題是用二分求,最大化最小值。
#include <bits/stdc++.h> using namespace std; int n,m,k,t; const int Max = 10005; int vis[Max]; struct edge{ int x,w; }; vector<edge> v[Max]; int bfs(int dis) { memset(vis,0,sizeof(vis)); queue<int> q; q.push(1); while(!q.empty()) { int cur = q.front(); q.pop(); if(cur==t) return true; if(vis[cur]==k) continue; int l = v[cur].size(); for(int i=0;i<l;i++) { int tmp = v[cur][i].x; if(vis[tmp]||v[cur][i].w>dis) continue; vis[tmp]=vis[cur]+1; q.push(tmp); } } return false; } int main() { int a,b,c; while(~scanf("%d%d%d%d",&n,&m,&k,&t)) { int a,b,c,maxn=0; for(int i=0;i<m;i++) { scanf("%d%d%d",&a,&b,&c); edge tmp; tmp.x = b; tmp.w = c; v[a].push_back(tmp); tmp.x = a; v[a].push_back(tmp); maxn = max(maxn,c); } int mid,l=0,r=maxn; while(l<=r) { mid = (l+r)/2; if(bfs(mid)){ r=mid-1; }else{ l=mid+1; } } printf("%d\n",l); } return 0; }