• 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
    ");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
    ",ans);
    }



  • 相关阅读:
    诸侯安置
    可可西里
    直线交点
    切割多边形
    ACM挑战程序设计竞赛1.1抽签
    朝鲜战争:轰炸大小和岛
    星际争霸II 战斗问题
    乒乓球
    瑞士轮
    NOIP 2010 普及组解题报告
  • 原文地址:https://www.cnblogs.com/Drenight/p/8611210.html
Copyright © 2020-2023  润新知