zoukankan      html  css  js  c++  java
  • 最小割树(洛谷4897)

    最小割树

    求任意两点间的最小割

    每次把当前点集中任意两点uv作为源汇跑最小割,连一条uv之间权值为最小割的边,之后按照分成的集合向下做

    判断一条边是否为割边就直接判当前方向即可,注意可以走非当前集合的点

    两点间最小割=新图中路径上的最小边权

    证明:https://blog.csdn.net/axxgo7/article/details/54619560

    code

    要考虑0

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    #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<b?a:b)
    #define inf 2133333333
    //#define file
    #define debug
    using namespace std;
    
    int aa[1111][3];
    int Ls[512];
    int a[3102][3];
    int A[3102];
    int ls[512];
    int cur[512];
    int f[512];
    int g[512];
    int d[512][512];
    int b[512];
    int bz[512];
    int d2[512];
    int fa[512][9];
    int mn[512][9];
    int D[512];
    bool Bz[512];
    int Q,n,m,i,j,k,l,len,st,ed,Len,h2,t2,x,y;
    
    void New(int x,int y,int z)
    {
    	++len;
    	a[len][0]=y;
    	a[len][1]=ls[x];
    	ls[x]=len;
    	a[len][2]=A[len]=z;
    }
    
    void NEW(int x,int y,int z)
    {
    	++Len;
    	aa[Len][0]=y;
    	aa[Len][1]=Ls[x];
    	Ls[x]=Len;
    	aa[Len][2]=z;
    }
    
    int dfs(int t,int flow)
    {
    	int i,use=0;
    	
    	if (t==ed)
    	return flow;
    	
    	for (i=cur[t]; i; i=a[i][1])
    	{
    		cur[t]=i;
    		
    		if (f[t]==f[a[i][0]]+1 && a[i][2])
    		{
    			int w=dfs(a[i][0],min(flow-use,a[i][2]));
    			
    			a[i][2]-=w;
    			a[i^1][2]+=w;
    			use+=w;
    			
    			if (use==flow)
    			return use;
    		}
    	}
    	cur[t]=ls[t];
    	
    	--g[f[t]];
    	if (!g[f[t]])
    	{
    		f[st]=n+1;
    		return use;
    	}
    	++f[t];++g[f[t]];
    	
    	return use;
    }
    
    void work(int t)
    {
    	int Ans=0;
    	
    	if (b[t]<=1)
    	return;
    	
    	memset(f,0,sizeof(f));
    	memset(g,0,sizeof(g));
    	fo(i,1,len) a[i][2]=A[i];
    	
    	g[0]=n;
    	st=d[t][1];
    	ed=d[t][2];
    	
    	while (f[st]<=n)
    	Ans+=dfs(st,inf);
    	
    	NEW(st,ed,Ans);
    	NEW(ed,st,Ans);
    	
    	b[t+1]=1;
    	d[t+1][1]=st;
    	bz[st]=t+1;
    	
    	memset(Bz,0,sizeof(Bz));Bz[st]=1;
    	h2=0;t2=1;
    	d2[1]=st;
    	while (h2<t2)
    	{
    		for (i=ls[d2[++h2]]; i; i=a[i][1])
    		if (a[i][2] && !Bz[a[i][0]])
    		{
    			Bz[a[i][0]]=1;
    			d2[++t2]=a[i][0];
    			
    			if (bz[a[i][0]]==t)
    			{
    				bz[a[i][0]]=t+1;
    				d[t+1][++b[t+1]]=a[i][0];
    			}
    		}
    	}
    	work(t+1);
    	
    	b[t+1]=0;
    	fo(i,1,b[t])
    	if (bz[d[t][i]]==t+1)
    	bz[d[t][i]]=t;
    	else
    	if (bz[d[t][i]]==t)
    	{
    		d[t+1][++b[t+1]]=d[t][i];
    		bz[d[t][i]]=t+1;
    	}
    	
    	work(t+1);
    	fo(i,1,b[t])
    	if (bz[d[t][i]]==t+1)
    	bz[d[t][i]]=t;
    }
    
    void swap(int &x,int &y)
    {
    	int z=x;
    	x=y;
    	y=z;
    }
    
    int js(int x,int y)
    {
    	int i,ans=inf;
    	
    	if (D[x]<D[y])
    	swap(x,y);
    	
    	fd(i,8,0)
    	if (D[fa[x][i]]>=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
    ",js(x,y));
    	}
    }
    
  • 相关阅读:
    多测师讲解htm_L标题标签001_高级讲师 肖sir
    Shell特殊变量介绍与实践 $0
    shell 变量定义技巧总结
    shell 环境变量的知识小结
    前端 chrome查看html样式基本操作
    shell 命令 env
    date 命令
    shell 命令 set命令
    shell export 命令
    前端 html span标签
  • 原文地址:https://www.cnblogs.com/gmh77/p/12089135.html
Copyright © 2011-2022 走看看