いろいろがんばりたいブログ

情報科学科の人がいろいろ書きます。

POJ 3662 Telephone Lines

解を二分探索 + ダイクストラ

// compile in C++11. use -std=c++11.
#include <iostream>
#include <iomanip>
#include <vector>
#include <valarray>
#include <map>
#include <set>
#include <list>
#include <queue>
#include <stack>
#include <bitset>
#include <utility>
#include <numeric>
#include <algorithm>
#include <functional>
#include <complex>
#include <string>
#include <sstream>

#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cstring>


using namespace std;

#define all(c) c.begin(),c.end()
#define repeat(i,n) for(int i=0;i<static_cast<int>(n);i++)
#define debug(x) #x << "=" << (x)
#define dump(x) cerr << debug(x) << " (L:" << __LINE__ << ")"<< endl

struct Edge{
    int to,cost;
    Edge(int to_,int cost_)
        : to(to_),cost(cost_) {
    }
};

int mydijkstra(const int start,const int goal,const int u,
             const vector<vector<Edge> > &graph){
    typedef pair<int,int> pii;
    int N = graph.size();
    vector<char> visited(N,false);
    // cost where
    priority_queue<pii,vector<pii>,greater<pii> > que;
    que.push(make_pair(0,start));
    while(not que.empty()){
        int cost,where;
        cost = que.top().first;
        where = que.top().second;
        que.pop();
        if(visited[where]) continue;
        if(where == goal) return cost;
        visited[where] = true;
        for(int j=0;j<(int)graph[where].size();j++){
            if(graph[where][j].cost <= u){
                que.push(make_pair(cost,graph[where][j].to));
            }else{
                que.push(make_pair(1+cost,graph[where][j].to));
            }

        }
    }
    return -1;
}

int solve(const int N,const int P,const int K,
          const vector<int> &A,
          const vector<int> &B,
          const vector<int> &L){
    const int INF = 1000001;
    int lower = 0;
    int upper = INF;

    // いくら払うかで二分探索。
    //  K本ただで貰える。 -> K+1本目の枝
    vector<vector<Edge> > graph(N);
    repeat(i,P){
        graph[A[i]].push_back(Edge(B[i],L[i]));
        graph[B[i]].push_back(Edge(A[i],L[i]));
    }

    repeat(bin_search,20){
        int mid = (lower+upper)/2;
        int d = mydijkstra(0,N-1,mid,graph);
        // ok
        if(0 <= d and d <= K){
            upper = mid;
        }else{
            lower = mid;
        }
    }
    if(upper >= INF) return -1;
    return upper;
}

int main(){
    int N,P,K;
    cin >> N >> P >> K;
    vector<int> A(P),B(P),L(P);
    repeat(i,P){
        scanf("%d %d %d",&A[i],&B[i],&L[i]);
        A[i]--;
        B[i]--;
    }
    cout << solve(N,P,K,A,B,L) << endl;
    return 0;
}