您的位置:首页 > 其它

【kruscal】【最小生成树】【块状树】bzoj3732 Network

2014-10-04 09:06 519 查看
跟去年NOIP某题基本一样。

最小生成树之后,就变成了询问连接两点的路径上的权值最大的边。

倍增LCA、链剖什么的随便搞。

块状树其实也是很简单的,只不过每个点的点权要记录成“连接其与其父节点的边的权值”,然后暴力LCA时不要用LCA的值更新答案了。

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 15001
int Res,Num;char C,CH[20];
inline int Ge()
{
Res=0;C='*';
while(C<'0'||C>'9')C=getchar();
while(C>='0'&&C<='9'){Res=Res*10+(C-'0');C=getchar();}
return Res;
}
inline void P(int x)
{
Num=0;if(!x){putchar('0');puts("");return;}
while(x>0)CH[++Num]=x%10,x/=10;
while(Num)putchar(CH[Num--]+48);
putchar('\n');
}
struct Edge{int u,v,w;void Read(){u=Ge();v=Ge();w=Ge();}};
bool cmp(const Edge &a,const Edge &b){return a.w<b.w;}
Edge edges[maxn<<1];
struct Graph
{
int v[maxn<<1],first[maxn<<1],next[maxn<<1],w[maxn<<1],en;
void AddEdge(const int &a,const int &b)
{v[++en]=b;next[en]=first[a];first[a]=en;}
void AddEdge(const int &a,const int &b,const int &c)
{v[++en]=b;w[en]=c;next[en]=first[a];first[a]=en;}
};
Graph G[2];
int fa[maxn],dep[maxn],top[maxn],siz[maxn],sz,maxv[maxn],W[maxn];
int n,m,q,x,y;
void makeblock(int cur)
{
for(int i=G[0].first[cur];i;i=G[0].next[i])
if(G[0].v[i]!=fa[cur])
{
dep[G[0].v[i]]=dep[cur]+1;
W[G[0].v[i]]=G[0].w[i];
fa[G[0].v[i]]=cur;
if(siz[top[cur]]<sz)
{
siz[top[cur]]++;
top[G[0].v[i]]=top[cur];
G[1].AddEdge(cur,G[0].v[i]);
}
makeblock(G[0].v[i]);
}
}
int rank[maxn],father[maxn];
void init(){for(int i=1;i<=n;i++) father[i]=i;}
int findroot(int x)
{
if(father[x]==x) return x;
int rt=findroot(father[x]);
father[x]=rt;
return rt;
}
void Union(int U,int V)
{
if(rank[U]<rank[V]) father[U]=V;
else
{
father[V]=U;
if(rank[U]==rank[V]) rank[U]++;
}
}
void dfs(int cur,int Maxnow)
{
maxv[cur]=Maxnow;
for(int i=G[1].first[cur];i;i=G[1].next[i])
dfs(G[1].v[i],max(Maxnow,W[G[1].v[i]]));
}
int Query_max(int u,int v)
{
int res=-2147483647;
while(u!=v)
{
if(top[u]==top[v])
{
if(dep[u]<dep[v]) swap(u,v);
res=max(res,W[u]);
u=fa[u];
}
else
{
if(dep[top[u]]<dep[top[v]]) swap(u,v);
res=max(res,maxv[u]);
u=fa[top[u]];
}
}
return res;
}
int main()
{
n=Ge();m=Ge();q=Ge();
for(int i=1;i<=m;i++) edges[i].Read();
sort(edges+1,edges+m+1,cmp);
init();
int cnt=0;
for(int i=1;i<=m;i++)
{
int f1=findroot(edges[i].u),f2=findroot(edges[i].v);
if(f1!=f2)
{
Union(f1,f2);
G[0].AddEdge(edges[i].u,edges[i].v,edges[i].w);
G[0].AddEdge(edges[i].v,edges[i].u,edges[i].w);
cnt++;
if(cnt==n-1) break;
}
}
sz=sqrt(n);
for(int i=1;i<=n;i++)
{
top[i]=i;
siz[i]=1;
}
makeblock(1);
for(int i=1;i<=n;i++) if(top[i]==i) dfs(i,W[i]);
for(int i=1;i<=q;i++) {x=Ge();y=Ge();P(Query_max(x,y));}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: