货车运输(LCA+最大生成树)
货车运输
这题会有重边,又因为求的是尽可能大的边中的最小值,所以我们可以先用最大生成树维护,如何用最大生成树呢?可以用Kruskal和并查集,顺便处理重边,处理完重边后,可以用倍增LCA求两点之间的最大载重量
处理重边时,必须把dis在x,y相同情况下大的排在前,以保证最优,用并查集find判断是否是重边
建完以后,有环图便成了一棵树
点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int N = 50010;
int n,m,q;
int a[N/5],cnt,head[N/5];
int d[N/5],f[N/5][23],fa[N/5];bool vis[N/5];
struct EDGE
{
int from,to,next,w;
}edge[N*2];
struct ED
{
int x,y,dis;
}e1[N];
bool cmp(ED a,ED b)
{
return a.dis>b.dis;
}
void add(int u,int v,int w)
{
edge[++cnt].from=u;
edge[cnt].to=v;
edge[cnt].next=head[u];
edge[cnt].w=w;
head[u]=cnt;
}
int find(int x)
{
if(fa[x]!=x)
{
fa[x]=find(fa[x]);
}
return fa[x];
}
void kruskal()
{
sort(e1+1,e1+1+m,cmp);
for(int i=1;i<=n;i++)fa[i]=i;
for(int i=1;i<=m;i++)
{
int x=find(e1[i].x),y=find(e1[i].y);
if(x==y)continue;
fa[y]=x;
add(e1[i].x,e1[i].y,e1[i].dis);add(e1[i].y,e1[i].x,e1[i].dis);
}
return;
}
int dis[N/5][23];
void dfs(int x)
{
vis[x]=1;
for(int i=head[x];i;i=edge[i].next)
{
int to=edge[i].to;
if(vis[to])continue;
dis[to][0]=edge[i].w;
d[to]=d[x]+1;
f[to][0]=x;
dfs(to);
}
}
void dfs_init()
{
for(int j=1;j<23;j++)
{
for(int i=1;i<=n;i++)
{
f[i][j]=f[f[i][j-1]][j-1];
dis[i][j]=min(dis[i][j-1],dis[f[i][j-1]][j-1]);
}
}
}
int lca(int x,int y)
{
int ans=INT_MAX;
if(d[x]<d[y])swap(x,y);
// int D=d[x]-d[y];
for(int i=22;i>=0;i--)
{
if(d[f[x][i]]>=d[y])//i&
{
ans=min(ans,dis[x][i]),x=f[x][i];
// cout<<x<<endl;
}
}
if(x==y)return ans;
for(int i=22;i>=0;i--)
{
if(f[x][i]!=f[y][i])
{
ans=min({ans,dis[x][i],dis[y][i]});
x=f[x][i];
y=f[y][i];
}
}
ans=min({ans,dis[x][0],dis[y][0]});//不要忘记自身比较,否则会少情况
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
int x,y,z;
// memset(dis,0x3f,sizeof(dis));
// for(int i=1;i<=n;i++)
// for(int j=0;j<23;j++)dis[i][j]=INT_MAX;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&e1[i].x,&e1[i].y,&e1[i].dis);
}
kruskal();
scanf("%d",&q);
for(int i=1;i<=n;i++)
if(!vis[i])
{
f[i][0]=i;
d[i]=1;
dfs(i);
dis[i][0]=INT_MAX;
}
dfs_init();
// for(int i=1;i<=n;i++)cout<<dis[i][0]<<" ";
// cout<<endl;
for(int i=1;i<=q;i++)
{
scanf("%d%d",&x,&y);
int rx=find(x);int ry=find(y);
if(rx!=ry)
{
printf("-1\n");
}else
{
// cout<<x<<" "<<y<<endl;
printf("%d\n",lca(x,y));
}
}
return 0;
}
/*
4 4
1 2 4
2 3 3
3 1 1
1 2 5
3
1 3
1 4
1 3
*/