最小割树
求任意两点间的最小割
每次把当前点集中任意两点uv作为源汇跑最小割,连一条uv之间权值为最小割的边,之后按照分成的集合向下做
判断一条边是否为割边就直接判当前方向即可,注意可以走非当前集合的点
两点间最小割=新图中路径上的最小边权
证明:https://blog.csdn.net/axxgo7/article/details/54619560
code
要考虑0
#include
#include
#include
#include
#include
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(a,b) (a=D[y])
ans=min(ans,mn[x][i]),x=fa[x][i];
fd(i,8,0)
if (fa[x][i]!=fa[y][i])
ans=min(ans,min(mn[x][i],mn[y][i])),x=fa[x][i],y=fa[y][i];
if (x!=y) ans=min(ans,min(mn[x][0],mn[y][0]));
return ans;
}
void Dfs(int Fa,int t)
{
int i;
fa[t][0]=Fa;
D[t]=D[Fa]+1;
fo(i,1,8)
fa[t][i]=fa[fa[t][i-1]][i-1],mn[t][i]=min(mn[t][i-1],mn[fa[t][i-1]][i-1]);
for (i=Ls[t]; i; i=aa[i][1])
if (aa[i][0]!=Fa)
{
mn[aa[i][0]][0]=aa[i][2];
Dfs(t,aa[i][0]);
}
}
int main()
{
#ifdef file
freopen("luogu4897.in","r",stdin);
#ifdef debug
freopen("b.out","w",stdout);
#endif
#endif
scanf("%d%d",&n,&m);len=1;++n;
fo(i,1,m)
{
scanf("%d%d%d",&j,&k,&l);
++j;++k;
New(j,k,l);
New(k,j,l);
}
b[0]=n;
fo(i,1,n)
d[0][i]=i;
work(0);
Dfs(0,1);
scanf("%d",&Q);
for (;Q;--Q)
{
scanf("%d%d",&x,&y);++x;++y;
printf("%d\n",js(x,y));
}
}