zoukankan      html  css  js  c++  java
  • [bzoj4519][Cqoi2016]不同的最小割_网络流_最小割_最小割树

    不同的最小割 bzoj-4519 Cqoi-2016

    题目大意题目链接

    注释:略。


    想法

    我们发现这和最小割那题比较像。

    我们依然通过那个题说的办法一样,构建最小割树即可。

    接下来就是随便怎么处理都行了。

    我们可以弄一个数组把枚举到的距离都记录下来即可。

    Code

    #include <bits/stdc++.h>
    #define N 860
    #define M 17010
    using namespace std;
    queue<int> q;
    int n,head[N],to[M],val[M],next[M],tot=1,s,t,dis[N],a[N],tmp[N],ans[N][N],v[1000000],tot;
    inline void add(int x,int y,int z)
    {
    	to[++tot]=y,val[tot]=z,next[tot]=head[x],head[x]=tot;
    	to[++tot]=x,val[tot]=z,next[tot]=head[y],head[y]=tot;
    }
    bool bfs()
    {
    	int x,i;
    	memset(dis,0,sizeof(dis));
    	while(!q.empty()) q.pop();
    	dis[s]=1,q.push(s);
    	while(!q.empty())
    	{
    		x=q.front(),q.pop();
    		for(i=head[x];i;i=next[i])
    		{
    			if(val[i]&&!dis[to[i]])
    			{
    				dis[to[i]]=dis[x]+1;
    				if(to[i]==t) return 1;
    				q.push(to[i]);
    			}
    		}
    	}
    	return 0;
    }
    int dinic(int x,int low)
    {
    	if(x==t) return low;
    	int temp=low,i,k;
    	for(i=head[x];i;i=next[i])
    	{
    		if(val[i]&&dis[to[i]]==dis[x]+1)
    		{
    			k=dinic(to[i],min(temp,val[i]));
    			if(!k) dis[to[i]]=0;
    			val[i]-=k,val[i^1]+=k;
    			if(!(temp-=k)) break;
    		}
    	}
    	return low-temp;
    }
    void solve(int l,int r)
    {
    	if(l >= r) return;
    	int i,j,sum=0,p1,p2;
    	for(i=2;i <= tot;i+=2) val[i]=val[i^1]=(val[i]+val[i^1]) >> 1;
    	s=a[l],t=a[r];
    	while(bfs()) sum+=dinic(s,1<<30);
    	for(i=1;i <= n;i++)
    		if(dis[i])
    			for(j=1;j <= n;j++)
    				if(!dis[j])
    					ans[i][j]=ans[j][i]=min(ans[i][j],sum);
    	for(p1=i=l,p2=r;i <= r;i++)
    	{
    		if(dis[a[i]]) tmp[p1++]=a[i];
    		else tmp[p2--]=a[i];
    	}
    	for(i=l;i <= r;i++) a[i]=tmp[i];
    	solve(l,p2),solve(p1,r);
    }
    int main()
    {
    	int m,i,j,x,y,z,ret=0;
    	scanf("%d%d",&n,&m);
    	while(m--) scanf("%d%d%d",&x,&y,&z),add(x,y,z);
    	for(i=1;i <= n;i++) a[i]=i;
    	memset(ans,0x7f,sizeof(ans)),solve(1,n);
    	for(i=1;i <= n;i++)
    		for(j=i+1;j <= n;j++)
    			v[++tot]=ans[i][j];
    	sort(v+1,v+tot+1);
    	v[0]=-1<<30;
    	for(i=1;i <= tot;i++)
    		if(v[i] != v[i-1])
    			ret++;
    	printf("%d
    ",ret);
    	return 0;
    }
    

    小结:最小割树的应用我就碰见了这么两道题。

  • 相关阅读:
    OleDbCommand 的用法
    递归求阶乘
    C#重写窗体的方法
    HDU 5229 ZCC loves strings 博弈
    HDU 5228 ZCC loves straight flush 暴力
    POJ 1330 Nearest Common Ancestors LCA
    HDU 5234 Happy birthday 01背包
    HDU 5233 Gunner II 离散化
    fast-IO
    HDU 5265 pog loves szh II 二分
  • 原文地址:https://www.cnblogs.com/ShuraK/p/10246211.html
Copyright © 2011-2022 走看看