首页 > 其他分享 >Codeforces 1835F - Good Graph

Codeforces 1835F - Good Graph

时间:2023-06-22 10:11:45浏览次数:47  
标签:Good int Graph 1835F ec dep MAXN ret hd

good problem,bad round。

判断 YES 还是 NO 很trivial,就直接跑最大匹配看看是不是 \(n\) 即可。

如果是 NO,那么考虑 Hall 定理的证明过程构造即可。具体方法就是找到左部任意一非匹配点,在残量网络上 BFS 可以到达的点,那所有可以到达的左部点形成的集合就是符合要求的反例。因为你肯定不会 BFS 到右部的非匹配点,而对于右边的匹配点,它左边的匹配点也一定在里面。

重点在于 YES 部分的求解。先发现一个很重要的性质:两个 Tight 集合的并也是 Tight 集合,证明是 trivial 的。因此考虑对每个左部点 \(i\) 找到最小的包含 \(i\) 的 Tight 集合 \(S_i\),那么两张图等价当且仅当所有 \(S_i\) 均相同。考虑找 \(S_i\) 的过程,显然是依次扩展左右部点集合直到它们相同。这里有一步很牛逼的图论转化我没有想到:对于每个左部点 \(i\) 以及右部点 \(j\) 满足 \(i,j\) 有边且 \(j\ne mch_i\),连一条 \(i\to mch_j\) 的边,这样 \(S_i\) 就是这张图上 \(i\) 能到达的点集。而二分图边数就是这张图中边数 \(+n\),因此问题进一步被规约为,找一张边数最小的图满足其传递闭包与原图相同,这个比较好做,先 bitset 做传递闭包,然后强连通分量缩个点,强连通分量内部连个环,外部的边就考虑是否存在一个中间点 \(z\) 满足存在 \(x\to z,z\to y\) 的路径,如果存在就把 \(x\to y\) 边删掉,同样可以 bitset 实现。

时间复杂度 \(n^{2.5}+\dfrac{n^3}{\omega}\)。

const int MAXN=1000;
const int MAXV=2000;
const int MAXE=3e6;
const int INF=0x3f3f3f3f;
int n,m,S,T,hd[MAXV+5],to[MAXE+5],nxt[MAXE+5],cap[MAXE+5],ec=1;
void adde(int u,int v,int f){
	to[++ec]=v;cap[ec]=f;nxt[ec]=hd[u];hd[u]=ec;
	to[++ec]=u;cap[ec]=0;nxt[ec]=hd[v];hd[v]=ec;
}
int dep[MAXV+5],now[MAXV+5];
bool getdep(){
	queue<int>q;memset(dep,-1,sizeof(dep));q.push(S);dep[S]=0;
	while(!q.empty()){
		int x=q.front();q.pop();now[x]=hd[x];
		for(int e=hd[x];e;e=nxt[e]){
			int y=to[e],z=cap[e];
			if(z&&!~dep[y]){dep[y]=dep[x]+1;q.push(y);}
		}
	}return ~dep[T];
}
int getflow(int x,int f){
	if(x==T)return f;int ret=0;
	for(int &e=now[x];e;e=nxt[e]){
		int y=to[e],z=cap[e];
		if(z&&dep[y]==dep[x]+1){
			int w=getflow(y,min(f-ret,z));
			ret+=w;cap[e]-=w;cap[e^1]+=w;
			if(f==ret)return ret;
		}
	}return ret;
}
int dinic(){int ret=0;while(getdep())ret+=getflow(S,INF);return ret;}
int mch[MAXV+5];
vector<int>g[MAXN+5],pt[MAXN+5];
bitset<MAXN+5>can[MAXN+5],A[MAXN+5],B[MAXN+5];
int dfn[MAXN+5],low[MAXN+5],vis[MAXN+5],stk[MAXN+5],tp,cmp,tim,bel[MAXN+5];
set<int>out[MAXN+5];
void tarjan(int x){
	dfn[x]=low[x]=++tim;stk[++tp]=x;vis[x]=1;
	for(int y:g[x]){
		if(!dfn[y])tarjan(y),chkmin(low[x],low[y]);
		else if(vis[y])chkmin(low[x],dfn[y]);
	}
	if(dfn[x]==low[x]){
		cmp++;int o;
		do{o=stk[tp--];vis[o]=0;bel[o]=cmp;}while(o^x);
	}
}
int main(){
	scanf("%d%d",&n,&m);S=n*2+1;T=n*2+2;
	for(int i=1;i<=n;i++)adde(S,i,1),adde(i+n,T,1);
	for(int i=1,u,v;i<=m;i++)scanf("%d%d",&u,&v),adde(u,v,1);
	if(dinic()!=n){
		puts("NO");
		static bool in[MAXV+5];
		for(int i=1;i<=n;i++)for(int e=hd[i];e;e=nxt[e])if(to[e]==S&&!cap[e]){
			queue<int>q;static bool vis[MAXV+5];
			vis[i]=1;q.push(i);
			while(!q.empty()){
				int x=q.front();q.pop();
				for(int e=hd[x];e;e=nxt[e])if(cap[e]&&to[e]!=S&&to[e]!=T&&!vis[to[e]])
					vis[to[e]]=1,q.push(to[e]);
			}
			vector<int>vec;
			for(int j=1;j<=n;j++)if(vis[j])vec.pb(j);
			printf("%d\n",vec.size());
			for(int x:vec)printf("%d ",x);printf("\n");
			return 0;
		}
	}
	puts("YES");
	for(int i=1;i<=n;i++)for(int e=hd[i];e;e=nxt[e])
		if(to[e]!=S&&cap[e^1])mch[i]=to[e],mch[to[e]]=i;
//	for(int i=1;i<=n*2;i++)printf("%d%c",mch[i]," \n"[i==n*2]);
	for(int i=1;i<=n;i++)for(int e=hd[i];e;e=nxt[e])
		if(to[e]!=S&&cap[e]){
//			printf("%d->%d\n",i,mch[to[e]]);
			g[i].pb(mch[to[e]]);can[i][mch[to[e]]]=1;
		}
	for(int k=1;k<=n;k++)for(int i=1;i<=n;i++)if(can[i][k])can[i]|=can[k];
	for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);
	for(int i=1;i<=n;i++)pt[bel[i]].pb(i);
	vector<pii>E;
	for(int i=1;i<=cmp;i++)if(pt[i].size()>1){
		for(int j=1;j<pt[i].size();j++)E.pb(mp(pt[i][j-1],pt[i][j]));
		E.pb(mp(pt[i].back(),pt[i][0]));
	}
	for(int i=1;i<=n;i++)for(int j:g[i])if(bel[i]!=bel[j])out[bel[i]].insert(bel[j]);
	for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(can[i][j])
		A[bel[i]][bel[j]]=B[bel[j]][bel[i]]=1;
	for(int i=1;i<=cmp;i++)A[i][i]=B[i][i]=1;
	for(int i=1;i<=cmp;i++)for(int j:out[i])if((A[i]&B[j]).count()==2)
		E.pb(mp(pt[i][0],pt[j][0]));
	printf("%d\n",E.size()+n);
	for(pii p:E)printf("%d %d\n",p.fi,mch[p.se]);
	for(int i=1;i<=n;i++)printf("%d %d\n",i,mch[i]);
	return 0;
}

标签:Good,int,Graph,1835F,ec,dep,MAXN,ret,hd
From: https://www.cnblogs.com/tzcwk/p/Codeforces-1835F.html

相关文章

  • 使用MaskableGraphic画线段-生成Mesh方式
    usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;usingUnityEngine.UI;usingUnityEngine.EventSystems;publicclassUGUIPoplateMesh:MaskableGraphic,IPointerEnterHandler,IPointerExitHandler{protectedoverridevoidO......
  • lilo java 快速 graphql stitching 包
    lilo是一个快速的graphqlstitching包,可以实现合并多个graphql服务的合并(schema,以及调用)比较适合的业务场景是gateway说明同时在springone官方中也有介绍到,内部使用到了graphql-java进行处理参考资料https://github.com/friatech/lilohttps://bitbucket.org/atlassian/graphql......
  • .NET中SQL数据库的GraphQL API
    您可能已经阅读了大量关于GraphQL的文章,并且已经了解了这种API技术的所有优缺点,作为RESTAPI的替代方案。但是,让我们不久回顾一下GraphQL是什么,它的主要目的,以及我们如何在现实生活中使用它。关于GraphQL的简短信息GraphQL于2015年由Facebook发布,定位为着名的RESTful架构风格的替代......
  • GraphQL vs RESTful
    REST作为一种现代网络应用非常流行的软件架构风格,自从RoyFielding博士在2000年他的博士论文中提出来到现在已经有了20年的历史。它的简单易用性,可扩展性,伸缩性受到广大Web开发者的喜爱。REST的API配合JSON格式的数据交换,使得前后端分离、数据交互变得非常容易,而且也已经成为了......
  • 推荐系统中的常用算法——基于Graph Embedding的GES和EGES
    1.概述相比较于基于CollaborativeFilter算法,基于基础GraphEmbedding模型可以根据用户的行为序列学习出item的embedding,利用item对应的Embedding可以方便计算item与item之间的相似度,并在实践中被证明是卓有成效的方法,在基于基础GraphEmbedding模型,主要包括item2vec,node2vec,deepw......
  • 当 GraphQL 遇上图数据库,便有了更方便查询数据的方式
    人之初,性本鸽。大家好,我叫储惠龙(实名上网),你可以叫我小龙人,00后一枚。目前从事后端开发工作。今天给大家带来一个简单的为NebulaGraph提供GraphQL查询支持的DEMO,为什么是简单的,因为本来想完成更多工作再给大家介绍的,但是上个月太忙加上下个月更忙,但是我又很想白嫖一下Neb......
  • [ABC305E] Art Gallery on Graph
    ArtGalleryonGraphの传送门Problem有一个由\(N\)个点\(M\)边的简单无向图,顶点编号为\(1\)到\(N\),边的编号为\(1\)到\(M\)。第$i$条边连接着点$a_i$和$b_i$。在一些点上有编号为\(1\)到\(K\)的\(K\)个守卫。守卫$i$位于顶点$p_i$,保护......
  • GoodNotes 5(mac手写笔记软件)
    GoodNotes5mac版是一款非常好用的手写笔记软件,GoodNotes5将会支持使用苹果系统的Mac电脑进行手写,并提供多种不同的笔刷来对字体进行书写。GoodNotes5这款软件采用了非常符合Mac用户习惯的界面,其手写风格和功能完全可以满足日常的记录需求。GoodNotes5在书写方面非常流畅,......
  • Graph Neural Networks Inspired by Classical Iterative Algorithms
    目录概符号说明MotivationRobustRegularizationYangY.,LiuT.,WangY.,ZhouJ.,GanQ.,WeiZ.,ZhangZ.,HuangZ.andWipfD.Graphneuralnetworksinspiredbyclassicaliterativealgorithms.ICML,2021.概基于广义energyfunction(diffusion)的图神经网......
  • 2023-06-10:给定一个由 n 个节点组成的网络,用 n x n 个邻接矩阵 graph 表示 在节点网络
    2023-06-10:给定一个由n个节点组成的网络,用nxn个邻接矩阵graph表示在节点网络中,只有当graph[i][j]=1时,节点i能够直接连接到另一个节点j。一些节点initial最初被恶意软件感染。只要两个节点直接连接,且其中至少一个节点受到恶意软件的感染,那么两个节点都将被恶意软件......