• bzoj 4519: [Cqoi2016]不同的最小割【最小割树Gomory–Hu tree】


    算法详见:http://www.cnblogs.com/lokiii/p/8191573.html
    求出点两两之间的最小割之后,把他们扔到map/set里跑即可
    可怕的是map和set跑的时间竟然完全一样…代码里注释掉的部分是map

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<map>
    #include<set>
    using namespace std;
    const int N=1005,M=100005,inf=1e9;
    int T,n,m,Q,a[N],h[N],cnt=1,s,t,q[N],le[N],ans[N][N],sum;
    bool v[N];
    map<int,bool>mp;
    set<int>st;
    struct qwe
    {
    	int ne,to,va;
    }e[M<<1];
    int read()
    {
    	int r=0,f=1;
    	char p=getchar();
    	while(p>'9'||p<'0')
    	{
    		if(p=='-')
    			f=-1;
    		p=getchar();
    	}
    	while(p>='0'&&p<='9')
    	{
    		r=r*10+p-48;
    		p=getchar();
    	}
    	return r*f;
    }
    void add(int u,int v,int w)
    {
    	cnt++;
    	e[cnt].ne=h[u];
    	e[cnt].to=v;
    	e[cnt].va=w;
    	h[u]=cnt;
    }
    bool bfs()
    {
    	queue<int>q;
    	memset(le,0,sizeof(le));
    	le[s]=1;
    	q.push(s);
    	while(!q.empty())
    	{
    		int u=q.front();
    		q.pop();
    		for(int i=h[u];i;i=e[i].ne)
    			if(e[i].va>0&&!le[e[i].to])
    			{
    				le[e[i].to]=le[u]+1;
    				q.push(e[i].to);
    			}
    	}
    	return le[t];
    }
    int dfs(int u,int f)
    {
    	if(u==t||!f)
    		return f;
    	int us=0;
    	for(int i=h[u];i&&us<f;i=e[i].ne)
    		if(e[i].va>0&&le[e[i].to]==le[u]+1)
    		{
    			int t=dfs(e[i].to,min(f-us,e[i].va));
    			e[i].va-=t;
    			e[i^1].va+=t;
    			us+=t;
    		}
    	if(!us)
    		le[u]=0;
    	return us;
    }
    int dinic()
    {
    	int re=0;
    	while(bfs())
    		re+=dfs(s,inf);
    	return re;
    }
    void dfs(int u)
    {
    	v[u]=1;
    	for(int i=h[u];i;i=e[i].ne)
    		if(e[i].va>0&&!v[e[i].to])
    			dfs(e[i].to);
    }
    void fen(int l,int r)
    {
    	if(l==r)
    		return;
    	for(int i=2;i<=cnt;i+=2)
    		e[i].va=e[i^1].va=(e[i].va+e[i^1].va)>>1;
    	s=a[l],t=a[r];
    	int tmp=dinic();
    	memset(v,0,sizeof(v));
    	dfs(s);
    	for(int i=1;i<=n;i++)
    		if(v[i])
    			for(int j=1;j<=n;j++)
    				if(!v[j])
    					ans[i][j]=ans[j][i]=min(ans[i][j],tmp);
    	int ll=l,rr=r;
    	for(int i=l;i<=r;i++)
    	{
    		if(v[a[i]])
    			q[ll++]=a[i];
    		else
    			q[rr--]=a[i];
    	}
    	for(int i=l;i<=r;i++)
    		a[i]=q[i];
    	fen(l,ll-1);
    	fen(rr+1,r);
    }
    int main()
    {
    	n=read(),m=read();
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=n;j++)
    			ans[i][j]=inf;
    	for(int i=1;i<=n;i++)
    		a[i]=i;
    	for(int i=1;i<=m;i++)
    	{
    		int u=read(),v=read(),w=read();
    		add(u,v,w);
    		add(v,u,w);
    	}
    	fen(1,n);
    	// for(int i=1;i<=n;i++)
    		// for(int j=i+1;j<=n;j++)
    			// if(!mp[ans[i][j]])
    			// {
    				// sum++;
    				// mp[ans[i][j]]=1;
    			// }
    	// printf("%d
    ",sum);
    	for(int i=1;i<=n;i++)
    		for(int j=i+1;j<=n;j++)
    			st.insert(ans[i][j]);
    	printf("%d
    ",st.size());
    	return 0;
    }
    
  • 相关阅读:
    jquery的img的动态title换行
    PHP小技巧
    Jquery zTree结合Asp.net实现异步加载数据
    Could not load type 'System.ServiceModel.Activation.HttpModule' from assembly 'System.ServiceModel, Version=3.0.0.0,"解决办法
    ORACLE使用数据泵导入导出部分表
    兼容IE、火狐、谷歌的页面关闭事件
    MySQL存储引擎总结
    linux常用基本命令
    PHP扩展模块Pecl、Pear以及Perl的区别
    php实现socket
  • 原文地址:https://www.cnblogs.com/lokiii/p/8192085.html
Copyright © 2020-2023  润新知