BZOJ1614 [Usaco2007 Jan]Telephone Lines架设电话线 二分/魔性剪枝/最小边长连通

拿到手感觉是二分。。就随性用并查集维护连通关系,bfs搜了搜,加了一大堆魔性剪枝,调了一年就过了

正解是二分之后最短路。。超mxlen的长1不超为0。。我是正解的两倍慢&&两倍长←_←

upd:我好像随手剪出了spfa啊233

#include<bits/stdc++.h>  
#pragma comment(linker, "/STACK:1024000000,1024000000")   
#include<stdio.h>  
#include<algorithm>  
#include<queue>  
#include<string.h>  
#include<iostream>  
#include<math.h>  
#include<set>  
#include<map>  
#include<vector>  
#include<iomanip>  
using namespace std;  
#define ll long long  
#define pb push_back  
#define FOR(a) for(int i=1;i<=a;i++)  
const int inf=0x3f3f3f3f;  
 
const int maxn=1e4+5;    
 
int n,p,k;
int fa[maxn];
void init(int n){for(int i=1;i<=n;i++)fa[i]=i;}
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
void unite(int a,int b){a=find(a);b=find(b);fa[a]=b;}

struct EDGE{
	int u,v,d;
};vector<EDGE>G[maxn];
vector<EDGE>edges;

struct NODE{int u;int cnt;};
queue<NODE>aaa;
int vis[maxn];
         
void dfs(int u,int fa,int maxlen){
	unite(u,1);
	for(int i=0;i<G[u].size();i++){
		if(G[u][i].d<=maxlen && find(G[u][i].v)!=1)dfs(G[u][i].v,u,maxlen);
	}
}

bool check(int mxlen){
	init(n);memset(vis,0x3f,sizeof vis);
	
	dfs(1,0,mxlen);
	
	if(find(n)==find(1))return 1;
	while(!aaa.empty()){aaa.pop();}
	NODE rt=(NODE){n,0};
	vis[n]=0;
	aaa.push(rt);

	while(!aaa.empty()){
		NODE now=aaa.front();aaa.pop();
		if(find(now.u)==find(1))return 1;
		if(vis[now.u]!=now.cnt)continue;

		for(int i=0;i<G[now.u].size();i++){
			if(find(now.u)==find(G[now.u][i].v))continue;
			if(vis[G[now.u][i].v] <= now.cnt)continue;


			if(G[now.u][i].d<=mxlen){
				vis[G[now.u][i].v]=now.cnt;
				aaa.push((NODE){G[now.u][i].v,now.cnt});
			}else{
				if(now.cnt+1<=k){
					if(vis[G[now.u][i].v]<=now.cnt+1)continue;
					vis[G[now.u][i].v]=now.cnt+1;
					aaa.push((NODE){G[now.u][i].v,now.cnt+1});
				}
			}

		}
	}
	return 0;
}

bool cmp(EDGE a,EDGE b){return a.d<b.d;}

int main(){
	scanf("%d%d%d",&n,&p,&k);
	int u,v,w;
	
	int l=0,r=0,ans=inf;
	
	init(n);
	FOR(p){
		scanf("%d%d%d",&u,&v,&w);
		G[u].pb((EDGE){u,v,w});
		G[v].pb((EDGE){v,u,w});
		edges.pb((EDGE){u,v,w});
		unite(u,v);
		r=max(r,w);
	}
	if(find(1)!=find(n)){
		printf("-1\n");return 0;
	}
	sort(edges.begin(),edges.end(),cmp);
	while(l<=r){

		int m=r+l>>1;
		if(check(m)){
			ans=min(m,ans);
			r=m-1;
		}else{
			l=m+1;
		}
	}
	printf("%d\n",ans);
}



posted @ 2017-12-02 01:22  Drenight  阅读(103)  评论(0编辑  收藏  举报