読者です 読者をやめる 読者になる 読者になる

pku 3662 Telephone Lines

問題概要:頂点数N(<=1000),辺の数P(<=10000)の重み(1以上1e6以下)付き無向グラフが与えられる 頂点1からNへの経路で、使った辺のうち好きなK本の重みを0にしていい時、使った辺のうち最も重い辺の最小値を答えよ


解答:にぶたん+01dijkstra
"重さwまでの辺を使っていいことにした時、1からNへ残りK本付け加えて辿り着けるなら答えはw以下"なので、wでにぶたん

実は01dijkstra書いたことなかった
どちらかというとdijkstraというよりかbfsだが、

if(d[e.to]>d[v]+e.cost)

の部分にdijkstraっぽさが残っている(これがないとこの図のとき死ぬ)
f:id:sigma425:20140719160458j:plain

コード:

#include <cstdio>
#include <iostream>
#include <vector>
#include <deque>
using namespace std;
#define rep(i,n) for(int i=0;i<n;++i)
#define rep1(i,n) for(int i=1;i<=n;++i)
#define all(c) (c).begin(),(c).end()
struct edge{int to,cost;};
vector<edge> G[1000];
deque<int> deq;
int a[10000],b[10000],l[10000],d[1000];
int main(){
	int n,p,k;
	scanf("%d%d%d",&n,&p,&k);
	rep(i,p){
		scanf("%d%d%d",a+i,b+i,l+i);
		a[i]--,b[i]--;
	}
	int ub=1e6+1,lb=-1;
	while(ub-lb>1){
		int m=(ub+lb)/2;
		rep(i,n) G[i].clear(),d[i]=1e8;
		rep(i,p){
			int cost=1;
			if(l[i]<=m) cost=0;
			G[a[i]].push_back({b[i],cost});
			G[b[i]].push_back({a[i],cost});
		}
		deq.clear();
		deq.push_front(0);
		d[0]=0;
		while(!deq.empty()){
			int v=deq.front();
			deq.pop_front();
			rep(i,G[v].size()){
				edge e=G[v][i];
				if(d[e.to]>d[v]+e.cost){
					if(e.cost==1){
						deq.push_back(e.to);
						d[e.to]=d[v]+1;
					}
					if(e.cost==0){
						deq.push_front(e.to);
						d[e.to]=d[v];
					}
				}
			}
		}
		if(d[n-1]<=k) ub=m;
		else lb=m;
	}
	if(ub==1e6+1) ub=-1;
	printf("%d\n",ub);
	return 0;
}