您的位置:首页 > 其它

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

2017-12-02 01:21 489 查看
拿到手感觉是二分。。就随性用并查集维护连通关系,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
=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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: