习题:Daleks' Invasion (hard)(LCA&冰茶姬)
题目
思路
我们随便找一棵最小生成树
之后将边分成两种:树边和非树边、
如果是非树边很好处理,直接LCA求最大值即可
考虑不是树边的情况,
如果把这条树边切开,有很多边连接两个连通块,我们所需要的知道的是除了这条边另外的所有边的最小值
这些最小值可以用树链剖分暴力维护,
当然也可以将边排序之后用类似于冰茶姬的方法进行维护
代码
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
namespace ufs
{
int fa[100005];
void makeset(int n)
{
for(int i=1;i<=n;i++)
fa[i]=i;
}
int findset(int x)
{
if(fa[x]==x)
return x;
return fa[x]=findset(fa[x]);
}
void merge(int u,int v)
{
int a=findset(u);
int b=findset(v);
fa[a]=b;
}
}
using namespace ufs;
struct edge
{
int u,v;
long long w;
int id;
friend bool operator < (const edge &a,const edge &b)
{
return a.w<b.w;
}
}a[1000005];
struct node
{
int e;
long long w;
};
int n,m;
int fath[100005],dep[100005],dp_ind[100005][25];
long long dp_w[100005][25];
long long ans[1000005],w[100005],val[100005];
bool vis[1000005];
vector<node> g[100005];
void dfs(int u,int fa)
{
dep[u]=dep[fa]+1;
for(int i=1;i<=20;i++)
{
dp_ind[u][i]=dp_ind[dp_ind[u][i-1]][i-1];
dp_w[u][i]=max(dp_w[u][i-1],dp_w[dp_ind[u][i-1]][i-1]);
}
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i].e;
if(v!=fa)
{
fath[v]=u;
dp_ind[v][0]=u;
dp_w[v][0]=g[u][i].w;
w[v]=g[u][i].w;
dfs(v,u);
}
}
}
long long lca(int u,int v)
{
long long maxx=0;
if(u==v)
return 0;
if(dep[u]>dep[v])
swap(u,v);
for(int i=20;i>=0;i--)
if(dep[u]<=dep[dp_ind[v][i]])
{
maxx=max(maxx,dp_w[v][i]);
v=dp_ind[v][i];
}
if(u==v)
return maxx;
for(int i=20;i>=0;i--)
if(dp_ind[u][i]!=dp_ind[v][i])
{
maxx=max(maxx,max(dp_w[u][i],dp_w[v][i]));
u=dp_ind[u][i];
v=dp_ind[v][i];
}
return max(maxx,max(dp_w[u][0],dp_w[v][0]));
}
void col(int u,int v,long long s)
{
while(u!=v)
{
if(dep[u]>dep[v])
swap(u,v);
val[v]=s;
merge(v,fath[v]);
v=findset(v);
}
}
int main()
{
memset(ans,-1,sizeof(ans));
memset(val,-1,sizeof(val));
cin>>n>>m;
for(int i=1;i<=m;i++)
{
cin>>a[i].u>>a[i].v>>a[i].w;
a[i].id=i;
}
sort(a+1,a+m+1);
makeset(n);
for(int i=1;i<=m;i++)
{
if(findset(a[i].u)!=findset(a[i].v))
{
merge(a[i].u,a[i].v);
vis[i]=1;
g[a[i].u].push_back((node){a[i].v,a[i].w});
g[a[i].v].push_back((node){a[i].u,a[i].w});
}
}
dfs(1,0);
makeset(n);
for(int i=1;i<=m;i++)
if(dep[a[i].u]>dep[a[i].v])
swap(a[i].u,a[i].v);
for(int i=1;i<=m;i++)
if(vis[i]==0)
col(findset(a[i].u),findset(a[i].v),a[i].w);
for(int i=1;i<=m;i++)
{
if(vis[i]==0)
ans[a[i].id]=lca(a[i].u,a[i].v);
else
ans[a[i].id]=val[a[i].v];
}
for(int i=1;i<=m;i++)
if(ans[i]==-1)
cout<<"1000000000\n";
else
cout<<ans[i]<<'\n';
return 0;
}

浙公网安备 33010602011771号