zoukankan      html  css  js  c++  java
  • [BZOJ4435][Cerc2015]Juice Junctions

    bzoj
    luogu

    description

    给你一张(n)(m)条边的无向图,保证每个点的度数不超过(3)。每条边容量为(1),求所有点对之间的最大流之和。
    (nle3000,mle4500)

    sol

    据说这题可以用最小割树跑过去。。。(mbox{orz})
    考虑一些靠谱一点的算法。因为最大流等于最小割,而一个点的度数不超过(3),所以任意两点之间的最大流应该(in{0,1,2,3})
    对于所有最大流(in{1,2,3})的点对,它们满足连通。
    对于所有最大流(in{2,3})的点对,它们满足在同一个边双连通分量中。
    对于所有最大流(=3)的点对,它们满足什么?
    满足任意删除一条边之后,它们仍在同一个边双连通分量中。
    所以就每次删一条边然后跑边双,(mbox{hash})一下所处的边双连通分量的编号就好啦。
    复杂度(O(nm))

    code

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int gi(){
    	int x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if (ch=='-') w=0,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return w?x:-x;
    }
    #define ull unsigned long long
    const int N = 3005;
    const int base1 = 20011118;
    const int base2 = 20020415;
    int n,m,fa[N],to[N*3],nxt[N*3],head[N],cnt=1,dfn[N],low[N],tim,S[N],bel[N],scc,ban,ans;
    ull hsh1[N],hsh2[N];
    void link(int u,int v){
    	to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;
    }
    int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
    void Tarjan(int u,int f){
    	dfn[u]=low[u]=++tim;S[++S[0]]=u;
    	for (int e=head[u];e;e=nxt[e]){
    		if (to[e]==f||e==ban||e==(ban^1)) continue;
    		if (!dfn[to[e]]) Tarjan(to[e],u),low[u]=min(low[u],low[to[e]]);
    		else low[u]=min(low[u],dfn[to[e]]);
    	}
    	if (dfn[u]==low[u]){
    		++scc;int x=0;
    		do x=S[S[0]--],bel[x]=scc; while (x!=u);
    	}
    }
    int main(){
    	n=gi();m=gi();
    	for (int i=1;i<=n;++i) fa[i]=i;
    	for (int i=1;i<=m;++i){
    		int u=gi(),v=gi();
    		link(u,v),link(v,u);
    		fa[find(u)]=find(v);
    	}
    	for (int i=1;i<=n;++i) if (!dfn[i]) Tarjan(i,0);
    	for (int i=1;i<=n;++i)
    		for (int j=i+1;j<=n;++j)
    			ans+=(find(i)==find(j))+(bel[i]==bel[j]);
    	for (int i=1;i<=m;++i){
    		memset(dfn,0,sizeof(dfn));tim=scc=0;
    		ban=i<<1;
    		for (int j=1;j<=n;++j) if (!dfn[j]) Tarjan(j,0);
    		for (int j=1;j<=n;++j) hsh1[j]=hsh1[j]*base1+bel[j],hsh2[j]=hsh2[j]*base2+bel[j];
    	}
    	for (int i=1;i<=n;++i)
    		for (int j=i+1;j<=n;++j)
    			ans+=(hsh1[i]==hsh1[j]&&hsh2[i]==hsh2[j]);
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    pointnet++之classification/train.py
    pointnet++的pytorch实现
    xavier初始化的简单推导
    z+f数据解析
    ubuntu安装dia
    卷积,reLu,池化的意义
    Split
    .net程序调试一:快速定位异常
    Memcached (第一篇)
    System.Web.Caching.Cache类 缓存 各种缓存依赖
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/9426493.html
Copyright © 2011-2022 走看看