搜索

luogu P4214 [CERC2015]Juice Junctions


发布时间: 2022-11-24 19:55:00    浏览次数:47 次

题面传送门

看到这道题的第一眼想法是这不是最小割树裸题吗,直接跑出最小割树然后暴力\(O(n^2)\)算答案就好了。

但是仔细想想似乎不是很对,因为你实际上这样跑网络流虽然是\(O(n+m)\)的但是还带个\(3\)倍常数,实际上Dicnic的常数还死大的……

我们考虑分类讨论,先算最小割至少为\(1\)的,显然就是一个联通块内部的点。

然后再算最小割至少为\(2\)的,可以发现两个点之间如果没有割边那么这两个点至少要割掉两条边。因此只需要求一个边双即可。

然后算最小割至少为\(3\)的,任意割掉一条边以后,一对点总是在一个边双内的点对显然要三条,否则两条。则枚举割掉的那条边然后暴力边双即可。然后要判断集合相等,显然哈希即可。

时间复杂度\(O(nm)\),听说边三联通分量能做到\(O(n+m)\)/xia

code:

#include<bits/stdc++.h>
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) ((m)*(x-1)+(y))
#define R(n) (rnd()%(n)+1)
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
#define PB push_back
using ll=long long;using db=double;using lb=long db;using ui=unsigned;using ull=unsigned ll;
using namespace std;const int N=4.5e3+5,M=N*4+5,K=1e5+5,mod=1e9+7,Mod=mod-1,INF=1e9+7;const db eps=1e-5;mt19937 rnd(time(0));
int Ans[N],n,m,k,x,y,z,X[N],Y[N],fa[N],Si[N],Ct,scc[N];ull f[N];
struct Edge{int x,id;};vector<Edge> S[N];
int GF(int x){return fa[x]^x?fa[x]=GF(fa[x]):x;}
namespace Tarjan{
	int low[N],dfn[N],st[N],sh,dh;
	void dfs(int x,int La){
		low[x]=dfn[x]=++dh;st[++sh]=x;for(Edge i:S[x])if(i.id^La){
			if(!dfn[i.x])dfs(i.x,i.id),low[x]=min(low[x],low[i.x]);
			else low[x]=min(low[x],dfn[i.x]);
		}if(low[x]==dfn[x]){++Ct;while(st[sh+1]^x) scc[st[sh]]=Ct,sh--;}
	}
	void GA(){Ct=0;sh=0;dh=0;Me(dfn,0);Me(st,0);Me(low,0);Me(scc,0);for(int i=1;i<=n;i++) !dfn[i]&&(dfs(i,0),0);}
}
ull P[N];map<ull,int> Ts;
int main(){
	freopen("1.in","r",stdin);
	int i,j,h;scanf("%d%d",&n,&m); for(i=1;i<=m;i++) scanf("%d%d",&X[i],&Y[i]),S[X[i]].PB((Edge){Y[i],i}),S[Y[i]].PB((Edge){X[i],i});
	for(i=1;i<=n;i++) fa[i]=i;for(i=1;i<=m;i++) fa[GF(X[i])]=GF(Y[i]);for(i=1;i<=n;i++) Si[GF(i)]++;
	for(i=1;i<=n;i++) Ans[i]+=Si[GF(i)];Me(Si,0);Tarjan::GA();for(i=1;i<=n;i++) Si[scc[i]]++;for(i=1;i<=n;i++) Ans[i]+=Si[scc[i]];
	for(i=1;i<=m;i++){
		for(auto j=S[X[i]].begin();j!=S[X[i]].end();j++) if((*j).x==Y[i]){S[X[i]].erase(j);break;} 
		for(auto j=S[Y[i]].begin();j!=S[Y[i]].end();j++) if((*j).x==X[i]){S[Y[i]].erase(j);break;}
		Tarjan::GA();S[X[i]].PB((Edge){Y[i],i});S[Y[i]].PB((Edge){X[i],i});
		for(j=1;j<=n;j++) f[j]=((ull)rnd()<<32)|rnd();for(j=1;j<=n;j++) P[j]^=f[scc[j]];
	}
	for(i=1;i<=n;i++) Ts[P[i]]++;for(i=1;i<=n;i++) printf("%d\n",Ans[i]+Ts[P[i]]-3);
}
免责声明 luogu P4214 [CERC2015]Juice Junctions,资源类别:文本, 浏览次数:47 次, 文件大小:-- , 由本站蜘蛛搜索收录2022-11-24 07:55:00。此页面由程序自动采集,只作交流和学习使用,本站不储存任何资源文件,如有侵权内容请联系我们举报删除, 感谢您对本站的支持。 原文链接:https://www.cnblogs.com/275307894a/p/16923027.html