货车运输
所以需要建立树,记录从特定起点到某处的限重的最大值,最大生成树
//kruskal可以保证树的生成是严格按照从大到小,保证答案的正确性
查询:x,y之间的lca
没了
#include<bits/stdc++.h> const int INF=19270817; using namespace std; int n,m,head[10005],q,tail,fa[10005][25],f[10005],dep[10005],maxn[10005][25]; struct edge { int x,y,v,nex; }e[100005]; edge b[100005]; void read(int &p) { p=0; int flag=1; char s=getchar(); while(!isdigit(s)) { if(s=='-') flag=-1; s=getchar(); } for(;isdigit(s);s=getchar()) p=p*10+s-'0'; p*=flag; } void add(int x,int y,int v) { e[++tail].x=x; e[tail].y=y; e[tail].v=v; } void add_edge(int x,int y,int v) { b[++tail].x=x; b[tail].y=y; b[tail].v=v; b[tail].nex=head[x]; head[x]=tail; } int getfa(int x) { if(f[x]==x) return f[x]; return f[x]=getfa(f[x]); } bool cmp(edge a,edge k) { return a.v>k.v; } //这是什么阴间使用方法?我怕不是个憨憨 void kruskal() { tail=0; int cnt=0; for(int i=1;i<=n;i++) f[i]=i; for(int i=1;i<=m;i++) { int f1=getfa(e[i].x),f2=getfa(e[i].y); if(f1!=f2) { f[f1]=f2; add_edge(e[i].x,e[i].y,e[i].v); add_edge(e[i].y,e[i].x,e[i].v); cnt++; } if(cnt==n-1) return ; } } void dfs(int x) { for(int i=head[x];i;i=b[i].nex) { int y=b[i].y; if(!dep[y]) { dep[y]=dep[x]+1; fa[y][0]=x; maxn[y][0]=b[i].v; dfs(y); } } } void first_deal() { for(int i=1;i<=n;i++) if(!dep[i]) { dep[i]=1; fa[i][0]=0; dfs(i); } for(int k=1;k<=20;k++) for(int i=1;i<=n;i++) { fa[i][k]=fa[fa[i][k-1]][k-1]; maxn[i][k]=min(maxn[i][k-1],maxn[fa[i][k-1]][k-1]); } } int ask(int x,int y) { if(getfa(x)!=getfa(y)) return -1; if(dep[x]<dep[y]) swap(x,y); int ans=INF; for(int i=20;i>=0;i--) { if(dep[fa[x][i]]>=dep[y]) { ans=min(ans,maxn[x][i]); x=fa[x][i]; } } if(x==y) return ans; for(int i=20;i>=0;i--) { if(fa[x][i]!=fa[y][i]) { ans=min(ans,min(maxn[x][i],maxn[y][i])); x=fa[x][i];y=fa[y][i]; } } ans=min(ans,min(maxn[x][0],maxn[y][0])); return ans; } int main() { read(n);read(m); int x,y,v; for(int i=1;i<=m;i++) { read(x);read(y);read(v); add(x,y,v); } sort(e+1,e+m+1,cmp); //注意这里的排序 kruskal(); //for(int i=1;i<=n;i++) f[i]=i; first_deal(); //预处理…… read(q); for(int i=1;i<=q;i++) { read(x);read(y); printf("%d\n",ask(x,y)); } return 0; }
#include<bits/stdc++.h>
const int INF=19270817;
using namespace std;
int n,m,head[10005],q,tail,fa[10005][25],f[10005],dep[10005],maxn[10005][25];
struct edge
{
int x,y,v,nex;
}e[100005];
edge b[100005];
void read(int &p)
{
p=0;
int flag=1;
char s=getchar();
while(!isdigit(s))
{
if(s=='-') flag=-1;
s=getchar();
}
for(;isdigit(s);s=getchar()) p=p*10+s-'0';
p*=flag;
}
void add(int x,int y,int v)
{
e[++tail].x=x;
e[tail].y=y;
e[tail].v=v;
}
void add_edge(int x,int y,int v)
{
b[++tail].x=x;
b[tail].y=y;
b[tail].v=v;
b[tail].nex=head[x];
head[x]=tail;
}
int getfa(int x)
{
if(f[x]==x) return f[x];
return f[x]=getfa(f[x]);
}
bool cmp(edge a,edge k)
{
return a.v>k.v;
}
//这是什么阴间使用方法?我怕不是个憨憨
void kruskal()
{
tail=0;
int cnt=0;
for(int i=1;i<=n;i++) f[i]=i;
for(int i=1;i<=m;i++)
{
int f1=getfa(e[i].x),f2=getfa(e[i].y);
if(f1!=f2)
{
f[f1]=f2;
add_edge(e[i].x,e[i].y,e[i].v);
add_edge(e[i].y,e[i].x,e[i].v);
cnt++;
}
if(cnt==n-1) return ;
}
}
void dfs(int x)
{
for(int i=head[x];i;i=b[i].nex)
{
int y=b[i].y;
if(!dep[y])
{
dep[y]=dep[x]+1;
fa[y][0]=x;
maxn[y][0]=b[i].v;
dfs(y);
}
}
}
void first_deal()
{
for(int i=1;i<=n;i++)
if(!dep[i])
{
dep[i]=1;
fa[i][0]=0;
dfs(i);
}
for(int k=1;k<=20;k++)
for(int i=1;i<=n;i++)
{
fa[i][k]=fa[fa[i][k-1]][k-1];
maxn[i][k]=min(maxn[i][k-1],maxn[fa[i][k-1]][k-1]);
}
}
int ask(int x,int y)
{
if(getfa(x)!=getfa(y)) return -1;
if(dep[x]<dep[y]) swap(x,y);
int ans=INF;
for(int i=20;i>=0;i--)
{
if(dep[fa[x][i]]>=dep[y])
{
ans=min(ans,maxn[x][i]);
x=fa[x][i];
}
}
if(x==y) return ans;
for(int i=20;i>=0;i--)
{
if(fa[x][i]!=fa[y][i])
{
ans=min(ans,min(maxn[x][i],maxn[y][i]));
x=fa[x][i];y=fa[y][i];
}
}
ans=min(ans,min(maxn[x][0],maxn[y][0]));
return ans;
}
int main()
{
read(n);read(m);
int x,y,v;
for(int i=1;i<=m;i++)
{
read(x);read(y);read(v);
add(x,y,v);
}
sort(e+1,e+m+1,cmp);
//注意这里的排序
kruskal();
//for(int i=1;i<=n;i++) f[i]=i;
first_deal();
//预处理……
read(q);
for(int i=1;i<=q;i++)
{
read(x);read(y);
printf("%d\n",ask(x,y));
}
return 0;
}