1. 程式人生 > >hihocoder 二分·二分答案【二分搜尋,最大化最小值】 (bfs)

hihocoder 二分·二分答案【二分搜尋,最大化最小值】 (bfs)

題目

這道題做了幾個小時了都沒有做出來,首先是題意搞了半天都沒有弄懂,難道真的是因為我不打遊戲所以連題都讀不懂了?

反正今天是弄不懂了,過幾天再來看看。。。

題意:一個人從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;
}