标签:bzoj bzoj3732 最小生成树 kruskal 倍增lca
题目大意:给定一个n个点m条边的无向连通图,k次询问两点之间所有路径中最长边的最小值
NOIP2013 货车运输,几乎就是原题。。。只不过最小边最大改成了最大边最小。。。
首先看到最大值最小第一反应二分答案 但是二分答案O(kmlogn)明显做不了 这里我们考虑最小生成树
先生成一棵最小生成树,然后每次询问利用倍增LCA求出路径上的最大权值即可
本蒟蒻居然把LCA写挂了。。。 而且样例还过了。。。 伤不起啊。。。
90%达成 剩下一道刷点啥呢。。。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
struct edge{
int x,y,f;
bool operator < (const edge &y) const
{
return f < y.f;
}
}edges[30300];
struct abcd{
int to,f,next;
}table[30300];
int head[15100],tot;
int n,m,k;
int fa[15100][20],f_max[15100][20],dpt[15100];
int belong[15100];
int find(int x)
{
if(!belong[x]||belong[x]==x)
return belong[x]=x;
return belong[x]=find(belong[x]);
}
void add(int x,int y,int z)
{
table[++tot].to=y;
table[tot].f=z;
table[tot].next=head[x];
head[x]=tot;
}
void dfs(int x)
{
int i;
dpt[x]=dpt[fa[x][0]]+1;
for(i=head[x];i;i=table[i].next)
{
if(table[i].to==fa[x][0])
continue;
fa[table[i].to][0]=x;
f_max[table[i].to][0]=table[i].f;
dfs(table[i].to);
}
}
int Query(int x,int y)
{
int j,re=0;
if(dpt[x]<dpt[y])
swap(x,y);
for(j=14;~j;j--)
if(dpt[ fa[x][j] ]>=dpt[y])
re=max(re,f_max[x][j]),x=fa[x][j];
if(x==y)
return re;
for(j=14;~j;j--)
if(fa[x][j]!=fa[y][j])
{
re=max(re,f_max[x][j]);
re=max(re,f_max[y][j]);
x=fa[x][j];
y=fa[y][j];
}
re=max(re,f_max[x][0]);
re=max(re,f_max[y][0]);
return re;
}
int main()
{
int i,j,x,y;
cin>>n>>m>>k;
for(i=1;i<=m;i++)
scanf("%d%d%d",&edges[i].x,&edges[i].y,&edges[i].f);
sort(edges+1,edges+m+1);
for(i=1;i<=m;i++)
{
int fx=find(edges[i].x),fy=find(edges[i].y);
if(fx!=fy)
{
belong[fx]=fy;
add(edges[i].x,edges[i].y,edges[i].f);
add(edges[i].y,edges[i].x,edges[i].f);
}
}
dfs(1);
for(j=1;j<=14;j++)
for(i=1;i<=n;i++)
fa[i][j]=fa[ fa[i][j-1] ][j-1],f_max[i][j]=max( f_max[i][j-1] , f_max[ fa[i][j-1] ][j-1] );
for(i=1;i<=k;i++)
{
scanf("%d%d",&x,&y);
printf("%d\n", Query(x,y) );
}
}
BZOJ 3732 Network Kruskal+倍增LCA
标签:bzoj bzoj3732 最小生成树 kruskal 倍增lca
原文地址:http://blog.csdn.net/popoqqq/article/details/39755703