构造有感

CF1450C Errich-Tac-Toe

首先考虑限制是每三个格子不能相同

考虑染色,即为 \((i+j)\mod3\)

然后考虑每一种颜色,有一个一定大于\(\dfrac{n}{3}\)

对于剩下的 \(\dfrac{2n}{3}\),实际上一共有 \(6\) 种情况

\(6\)种情况一共会修改\(2n\),一定有一种方案是修改在\(\dfrac{n}{3}\)以下的

\[OX. \\ XO.\\ 这两种情况总操作数小于\dfrac{2n}{3} \\ 其中有一个即为\dfrac{n}{3} \]

	#include<bits/stdc++.h>
	using namespace std;
	const int MAXN=405;
	int t;
	int n;
	int mp[MAXN][MAXN];
	int fyouucupk[MAXN][MAXN];
	char s[MAXN];
	int solve(string x)
	{
		int cnp=0;
		int byqflzh=0;
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				int dw=(i+j)%3;
				if((x[dw]!='0')&&(mp[i][j]))
				{
					fyouucupk[i][j]=x[dw]-'0';
				 } 
				 else
				 {
				 	fyouucupk[i][j]=mp[i][j];
				 }
			 } 
		 } 
		 for(int i=1;i<=n;i++)
		 {
		 	for(int j=1;j<=n;j++)
		 	{
		 		if(mp[i][j])
		 		{
		 			byqflzh++;
		 			cnp+=(mp[i][j]!=fyouucupk[i][j]);
				 }
			 }
		 }
		// printf("%d %d\n",cnp,byqflzh);
		 return cnp*3<=byqflzh;
	}
	void print()
	{
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				if(fyouucupk[i][j]==1)
				{
					printf("X");
				}
				else if(fyouucupk[i][j]==2)
				{
					printf("O");
				}
				else
				{
					printf(".");
				}
			}
			printf("\n");
		}
	}
	int main()
	{
		scanf("%d",&t);
		while(t--)
		{
			memset(mp,0,sizeof(mp));
			scanf("%d",&n);
			for(int i=1;i<=n;i++)
			{
				scanf("%s",s+1);
				for(int j=1;j<=n;j++)
				{
					if(s[j]=='X')
					{
						mp[i][j]=1;
					}
					else if(s[j]=='O')
					{
						mp[i][j]=2;
					}
				}
			}
			if(solve("120"))
			{
				print();
			 } 
			else if(solve("210"))
			{
				print();
			 } 
			else  if(solve("102"))
			{
				print();
			 } 
			else  if(solve("201"))
			{
				print();
			 } 
			else  if(solve("021"))
			{
				print();
			 } 
			 else if(solve("012"))
			{
				print();
			 } 
		}
	 } 


Mine Sweeper II

首先会发现地雷的数取决于相邻地雷与空格的边数

如果取反则总数不变

再考虑\(A与B\),\(A与(not\ B)\)

两个操作总数刚好为\(n*m\)

所以其中一个为\(\dfrac{n}{2}\)

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1005;
int n,m;
char s[MAXN];
int mpA[MAXN][MAXN];
int mpB[MAXN][MAXN];
int main()
{
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		scanf("%s",s+1);
		for(int j=1;j<=m;j++)
		{
			if(s[j]=='X')
			{
				mpA[i][j]=1;
			}
			else
			{
				mpA[i][j]=0;
			}
		}
	}
	
	for(int i=1;i<=n;i++)
	{
		scanf("%s",s+1);
		for(int j=1;j<=m;j++)
		{
			if(s[j]=='X')
			{
				mpB[i][j]=1;
			}
			else
			{
				mpB[i][j]=0;
			}
		}
	}
	int tot1=0,tot2=0;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++)
		{
			if(mpA[i][j]!=mpB[i][j])
			{
				tot1++;
			}
			else
			{
				tot2++;
			}
		}
	}
	if(tot1*2<=n*m)
	{
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				if(mpA[i][j]==1)
				{
					printf("X");
				 } 
				 else{
				 	printf(".");
				 }
			}
			printf("\n");
		}
		return 0;
	 } 
	if(tot2*2<=n*m)
	{
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				if((mpA[i][j]^1)==1)
				{
					printf("X");
				 } 
				 else{
				 	printf(".");
				 }
			}
			printf("\n");
		}
	 } 
	
}

CF1364D Ehab's Last Corollary

考虑一些\(DFS树\)性质

首先考虑环的条件,我们可以在\(DFS\)的时判环

对于无法满足所有环,瞎搞即可

#include<bits/stdc++.h>
using namespace std;
const int MAXN=3e5+5;
int n,m,k;
vector<int>g[MAXN];
int x,y;
int dfn[MAXN];
int cnt_dfn;
int deep[MAXN];
int fa[MAXN];
void dfs(int x,int f)
{
	dfn[x]=++cnt_dfn;
	for(int i=0;i<g[x].size();i++)
	{
		int v=g[x][i];
		if(v==f)
		{
			continue;
		}
		if(dfn[v])
		{
		//	printf("%d %d %d\n",x,v,deep[x]-deep[v]+1);
			if(dfn[v]<dfn[x])
			{
				int df=deep[x]-deep[v]+1;
				if(df<=k)
				{
					printf("2\n"); 
					int nx=x;
					printf("%d\n",df);
					while(nx!=v)
					{
						printf("%d ",nx);
						nx=fa[nx]; 
					}
					printf("%d",v);			 
					 exit(0);
				 } 
			}
			
		}
		else
		{
			deep[v]=deep[x]+1;
			fa[v]=x;
			dfs(v,x);
		}
	}
}

void DFS(int x,int f)
{
	dfn[x]=++cnt_dfn;
	for(int i=0;i<g[x].size();i++)
	{
		int v=g[x][i];
		if(v==f)
		{
			continue;
		}
		if(dfn[v])
		{
			if(dfn[v]<dfn[x]){
				int df=deep[x]+deep[v]+1;
				if(df>k)
				{
					int nx=x;
					int op=0,tot=0;
					while(nx!=v)
					{
						if((!op)&&(tot<(k+1)/2))
						{
							tot++;
							printf("%d ",nx);	
						}
						op^=1;
						nx=fa[nx]; 
					}
					if((!op)&&(tot<(k+1)/2))
					{
						tot++;
						printf("%d ",v);	
					}
					 exit(0);
				 } 
			}
			
		}
		else
		{
			deep[v]=deep[x]+1;
			fa[v]=x;
			DFS(v,x);
		}
	}
}
int main()
{
	scanf("%d %d %d",&n,&m,&k);
	for(int i=1;i<=m;i++){
		scanf("%d %d",&x,&y);
		g[x].push_back(y);
		g[y].push_back(x);
	}
	dfs(1,1);
	printf("1\n");
	int aim=(k+1)/2;
	if(m==n-1)
	{
		int tot1=0; 
		for(int i=1;i<=n;i++){
			if(deep[i]%2==0)
			{
				tot1++;
			}
		}
		if(tot1*2>=n)
		{
			tot1=0;
			
			for(int i=1;i<=n;i++)
			{
				if(deep[i]%2==0)
				{
					tot1++;
					printf("%d ",i);
				}
				if(tot1==aim)
				{
					break;
				}
			}
		}
		else
		{
			tot1=0;
			
			for(int i=1;i<=n;i++)
			{
				if(deep[i]%2==1)
				{
					tot1++;
					printf("%d ",i);
				}
				if(tot1==aim)
				{
					break;
				}
			}
		}
	}
	memset(dfn,0,sizeof(dfn));
	cnt_dfn=0;
	DFS(1,1); 
}

[IOI2019]景点划分

首先考虑\(a\leq b \leq c\) ,因为大小无所谓

因为要有两个联通块,所以,可以只需要划分两个最小的联通块,剩下的其实可以全部放在另一个联通块

问题转换为将图划分为两个联通块\((Siz_{min}=a,Siz_{max}=b,a\leq b \leq \dfrac{n}{2})\)和散点

再考虑将图划分为\(DFS序树\),考虑先处理树,如果树满足则一定可以转化到树上

问题即为将图划分为两个联通块\((Siz_{min}\geq a,Siz_{max}\geq b,a\leq b \leq \dfrac{n}{2})\),因此我们要尽量平均

考虑树的重心,重心下的连通块每一个都小于\(\dfrac{n}{2}\),如果不是,那当前状态下的重心一定不是最优

\(设重心上方的点集为T,下方儿子即为S_i\)

\(若Maximize(T,S_i)\geq a\)

重心下的最大的联通块大小一定小于\(\dfrac{n}{2}\),所以选择一块剩余部分一定可以满足\(B\)的条件

\(若Maximize(T,S_i)\leq a\)

因为\(DFS\)序的性质,返祖边只能手冲\(S\)连到\(T\),\(S\)之间不能连边

然后通过返祖边不断扩大\(T\),最后\(T\)的大小也不会超过\(2a\),而\(2a+b<a+b+c<n,n-2a>b\),所以这样加是满足的

#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e5+5;
int n,m;
struct Edge{
	int x,y;
}edge[MAXN];
vector<int>g[MAXN];
int x,y;
int a,b,c;
vector<pair<int,int> >TEACHER;
string PHYSICAL()
{
	
	TEACHER.push_back(make_pair(a,1));
	TEACHER.push_back(make_pair(b,2));
	TEACHER.push_back(make_pair(c,3));
	sort(TEACHER.begin(),TEACHER.end());
	a=TEACHER[0].first;
	b=TEACHER[1].first;
	return "Quan bu qu si"; 
 } 
 int dfn[MAXN];
 int Chemistry_teachersb;
 vector<int>G1[MAXN];
 vector<int>G2[MAXN];
 int Fa[MAXN];
 void dfs(int x,int f)
 {
 	dfn[x]=++Chemistry_teachersb;
 	for(int i=0;i<g[x].size();i++)
 	{
 		int v=g[x][i];
 		int w=g[x][i];
 		if(v==f)
		 {
		 	continue;
		  } 
		  if(dfn[v])
		  {
		  	if(dfn[v]<dfn[x])
		  	{
		  		G2[x].push_back(v);G2[v].push_back(x);
			  }
		  }
		  else
		  {
		  	G1[x].push_back(v);
		  	G1[v].push_back(x);
		  	Fa[v]=x;
		  	dfs(v,x);
		  }
	 }
 }
int Siz[MAXN];
int LSYISSB=0x3f3f3f3f;
int ZSJISSB;
void IAMSB(int x,int f){
	Siz[x]=1;
	int ZSLISSB=0;
	for(int i=0;i<G1[x].size();i++)
	{
		int v=G1[x][i];
		if(v==f)
		{
			continue;
		 } 
		 IAMSB(v,x);
		 Siz[x]=Siz[x]+Siz[v];
		 ZSLISSB=max(ZSLISSB,Siz[v]);
	}
	ZSLISSB=max(ZSLISSB,n-Siz[x]);
	if(ZSLISSB<LSYISSB)
	{
		LSYISSB=ZSLISSB;
		ZSJISSB=x;
	}
}
int Heart;
int AVID[MAXN];
vector<int>S[MAXN];
int cnts=0;
int AAA[MAXN];
int Cnta=0;
void FIND(int x,int f)
{
	S[cnts].push_back(x);
	for(int i=0;i<G1[x].size();i++)
	{
		int v=G1[x][i];
		if(v==f)
		{
			continue;
		}
		FIND(v,x);
	}
}
int Symbol[MAXN];
int Clor[MAXN];
void Find(int x,int f,int clo,int lit)
{
	if(lit==x)
	{
		return;
	}
	if(Symbol[x])
	{
		return;
	}
//	printf("%d\n",x);
	Symbol[x]=clo;
	for(int i=0;i<G1[x].size();i++)
	{
		int v=G1[x][i];
		if(v==f)
		{
			continue;
		}
		Find(v,x,clo,lit);
	 } 
}
int cnta=0;
int cntb=0;
void FFind(int x,int clo)
{
	
	if(Clor[x])
	{
		return;
	}
	if(Symbol[x]==clo)
	{
		if(clo==1)
		{
			if(cnta<a)
			{
				Clor[x]=1;
				cnta++;
			}
			else
			{
				return;
			}
		 } 
		 else if(clo==2)
		{
			if(cntb<b){
				Clor[x]=2;
				cntb++;
			}
			else
			{
				return;
			}
		}
		
	}
	else
	{
		return;
	}
	for(int i=0;i<G1[x].size();i++)
	{
		int v=G1[x][i];
		FFind(v,clo);
	}
	
	for(int i=0;i<G2[x].size();i++)
	{
		int v=G2[x][i];
		FFind(v,clo);
	}
}
int main()
{
//	freopen("4-27.in","r",stdin);
	scanf("%d %d",&n,&m);
	scanf("%d %d %d",&a,&b,&c);
	string Meaningless1=PHYSICAL();
	for(int i=1;i<=m;i++){
		scanf("%d %d",&x,&y);
		x++;
		y++;
		g[x].push_back(y);
		g[y].push_back(x); 
	}
	dfs(1,0);
	IAMSB(1,0);
	Heart=ZSJISSB;
	
	int nOwx=Heart;
	nOwx=Fa[nOwx];
	while(nOwx)
	{
		AVID[nOwx]=1;
		nOwx=Fa[nOwx];
	}
	for(int i=0;i<G1[Heart].size();i++)
	{
		int v=G1[Heart][i];
		if(v==Fa[Heart])
		{
			continue;
		}
		++cnts;
		FIND(v,Heart);
	}
	
	int Maxs=n-Siz[Heart];
	//int FUCKYZK;
	int Point=0;
	for(int i=1;i<=cnts;i++)
	{
		if(Maxs<S[i].size())
		{
			Maxs=S[i].size();
			Point=i;	
		}	
	}
	//printf("%d %d\n",Point,Maxs);
	if(Maxs>=a)
	{
		
		if(Point==0)
		{
		
			Find(1,0,1,Heart);
		//	
			Find(Heart,Fa[Heart],2,0);
			
			FFind(1,1);
			FFind(Heart,2);
		}
		else
		{
	//	printf("?");
			
			Find(S[Point][0],Heart,1,0);
			
			Find(1,0,2,Heart);
			
			Find(Heart,Fa[Heart],2,0);
			
			
			FFind(S[Point][0],1);
			
			FFind(1,2);
			//printf("-23");
		//	printf("%d %d\n",cnta,cntb);
		}
		
		for(int i=1;i<=n;i++)
		{
			if(Clor[i]==1)
			{
				printf("%d ",TEACHER[0].second);
			 } 
			 else if(Clor[i]==2)
			 {
			 	printf("%d ",TEACHER[1].second);
			 }
			 else
			 {
			 	printf("%d ",TEACHER[2].second);
			 }
		}
	}
	else
	{
		Find(1,0,1,Heart);
		int Nows=n-Siz[Heart];
		int zdskgs=0;
		for(int xsh=1;xsh<=n;xsh++)
		{
			if(Symbol[xsh]==1)
			{
				zdskgs++;
			}
		}
	//	printf("%d %d wrnm\n",Nows,zdskgs); 
		for(int i=1;i<=cnts;i++)
		{
			for(int j=0;j<S[i].size();j++){
				int Son=S[i][j];
				for(int k=0;k<G2[Son].size();k++)
				{
					int LH=G2[Son][k];
					if(AVID[LH])
					{
						AAA[i]=1;
						break;
					}
				}
			}
			if(AAA[i])
			{	
				Nows+=S[i].size();
				for(int j=0;j<S[i].size();j++){
					int Son=S[i][j];
					Symbol[Son]=1;
				}
				zdskgs=0;
				for(int xsh=1;xsh<=n;xsh++)
				{
					if(Symbol[xsh]==1)
					{
						zdskgs++;
					}
				}
			//	printf("%d %d %d wrnm\n",zdskgs,Nows,S[i].size());
				
				if(Nows>=a)
				{
					for(int lf=1;lf<=n;lf++)
					{
						if(Symbol[lf]!=1)
						{
							Symbol[lf]=2;
						}
					}
					zdskgs=0;
					for(int xsh=1;xsh<=n;xsh++)
					{
						if(Symbol[xsh]==1)
						{
							zdskgs++;
						}
					}
				//	printf("%dsdhgse\n",zdskgs);
					FFind(1,1);
				//	printf("%d\n",cnta);
					FFind(Heart,2);
				//	printf("%d %d\n",cnta,cntb);
					for(int ih=1;ih<=n;ih++)
					{
						if(Clor[ih]==1)
						{
							printf("%d ",TEACHER[0].second);
						 } 
						 else if(Clor[ih]==2)
						 {
						 	printf("%d ",TEACHER[1].second);
						 }
						 else
						 {
						 	printf("%d ",TEACHER[2].second);
						 }
						 
					}
					return 0;
				 } 
				 
			}
		}
		for(int i=1;i<=n;i++)
		{
			printf("0 "); 
		}
	}
//	int TS=n-Siz[Heart];
////	printf("%d\n",Heart);
//	int ILH=TS;
//	int IXF=0;
//	for(int i=1;i<=cnts;i++){
//	///	ILH=max(ILH,S[i].size());
//		if(S[i].size()>ILH)
//		{
//			ILH=S[i].size();
//			IXF=i;
//		}
//	}
//	if(ILH>=a)
//	{
//		if(IXF==0){
//			Cnta=0;
//			REFIND(1);
//			Cntb=0;
//		
//			RRRFIND(Heart);
//			for(int i=1;i<=n;i++)
//				{
//					if(Symbol[i]==1)
//					{
//						printf("%d ",TEACHER[0].second);
//					}
//					else if(Symbol[i]==2)
//					{
//						printf("%d ",TEACHER[1].second);
//					}
//					else
//					{
//						printf("%d ",TEACHER[2].second);
//					}
//				}
//		}
//		else
//		{
//		//	printf("%d--\n",S[IXF][0]);
//			Cnta=0;
//			RRFIND(S[IXF][0]);
//			Cntb=0;
//		//	printf("---%d\n",Heart); 
//			RRRFIND(Heart);
//			//?????
//			for(int i=1;i<=n;i++)
//				{
//					if(Symbol[i]==1)
//					{
//						printf("%d ",TEACHER[0].second);
//					}
//					else if(Symbol[i]==2)
//					{
//						printf("%d ",TEACHER[1].second);
//					}
//					else
//					{
//						printf("%d ",TEACHER[2].second);
//					}
//				}
//		}
//		return 0;
//	}
//	int IDSY=TS;
//	REFIND(1);
//	for(int i=1;i<=cnts;i++)
//	{
//		for(int j=0;j<S[i].size();j++){
//			int Son=S[i][j];
//			for(int k=0;k<G2[Son].size();k++)
//			{
//				int LH=G2[Son][k];
//				if(AVID[LH])
//				{
//					AAA[i]=1;
//					break;
//				}
//			}
//		}
//		if(AAA[i])
//		{
//			
//			
//			
//			if(IDSY+S[i].size()>=a)
//			{
//				Cnta=IDSY;
//				RRFIND(S[i][0]);
//				Cntb=0;
//				RRRFIND(Heart);
//				for(int igg=1;igg<=n;igg++)
//				{
//					if(Symbol[igg]==1)
//					{
//						printf("%d ",TEACHER[0].second);
//					}
//					else if(Symbol[igg]==2)
//					{
//						printf("%d ",TEACHER[1].second);
//					}
//					else
//					{
//						printf("%d ",TEACHER[2].second);
//					}
//				}
//				return 0;
//			}
//			else
//			{
//				IDSY+=S[i].size();
//				for(int j=0;j<S[i].size();j++){
//					int Son=S[i][j];
//					Symbol[Son]=1;
//				}
//			}
//		}
//	}
}
 

CF1391E Pairs of Pairs

首先建一棵DFS树,令\(k=\lceil\dfrac{n}{2}\rceil\)

然后分为两类\(dep< k\)\(dep\ge k\)

\(dep \ge k\)说明存在一条路径大于k

\(dep<k\)说明同一深度的两点可以互相匹配,就算个数为偶数也可以满足

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e6+5;
int t;
int n,m;
vector<int>g[MAXN],Rec[MAXN];
int x,y;
int cnt_dfn;
int dep[MAXN];
int dfn[MAXN];
vector<int>MAXD,D;
void dfs(int x,int f)
{
	dfn[x]=++cnt_dfn;
	D.push_back(x);
	if(D.size()>=((n%2==0)?(n/2):(n/2+1))&&MAXD.size()==0)
	{
		MAXD=D;
	 } 
	for(int i=0;i<g[x].size();i++)
	{
		int v=g[x][i];
		if(v==f)
		{
			continue;
		}
		if(dfn[v])
		{
			if(dfn[v]<dfn[x])
			{
				
			}
		}
		else
		{
			dep[v]=dep[x]+1;
			dfs(v,x);
		}
	}
	D.pop_back();
}
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d %d",&n,&m);
		cnt_dfn=0;
		for(int i=1;i<=n;i++)
		{
			dfn[i]=0;	
			g[i].clear();
			Rec[i].clear();
		}
		for(int i=1;i<=m;i++)
		{
			scanf("%d %d",&x,&y);
			g[x].push_back(y);
			g[y].push_back(x);		
		}
		MAXD.clear();
		D.clear();
		dep[1]=1;
		dfs(1,0);
		//int MAXD=0;
		for(int i=1;i<=n;i++)
		{
			//MAXD=max(MAXD,dep[i]);
			Rec[dep[i]].push_back(i);
		}
		if(MAXD.size()>=((n%2==0)?(n/2):(n/2+1)))
		{
			printf("PATH\n");
			printf("%d\n",MAXD.size());
			for(int i=0;i<MAXD.size();i++)
			{
				printf("%d ",MAXD[i]);
			}
			printf("\n");
		}
		else
		{
			vector<pair<int,int> >RRR;
			for(int i=1;i<=n;i++)
			{
				if(Rec[i].size()>=2)
				{
					for(int j=0;j<Rec[i].size()&&j+1<Rec[i].size();j+=2)
					{
						RRR.push_back(make_pair(Rec[i][j],Rec[i][j+1]));
					}
				}
			}
			printf("PAIRING\n");
			printf("%d\n",RRR.size());
			for(int i=0;i<RRR.size();i++)
			{
				printf("%d %d\n",RRR[i].first,RRR[i].second);
			}
		//	printf("\n");
		}
	}
 } 

CF1103C Johnny Solving

首先建一棵DFS树

分为两类\(dep< \lceil\dfrac{n}{k}\rceil\)\(dep\ge \lceil\dfrac{n}{k}\rceil\)

大于等于的可以直接选路径

小于的说明叶子个数大于k

因为\(dep[leaf]<\lceil\dfrac{n}{k}\rceil\),如果\(|leaf|<k\),则\(\sum dep[leaf]<n\),而实际上每条边都会被统计,所以矛盾

由一个叶子一定能构成环,这样也不会包含

具体就是两个祖先A,B

如果\(dep[A]-dep[leaf]+1\ mod\ 3=0\and dep[B]-dep[leaf]+1\ mod\ 3=0\)

\(dep[A]-dep[B] \mod 3=0\)

所以可以从A走到B

#include<bits/stdc++.h>
using namespace std;
const int MAXN=3e5+5;
int k;
int n,m;
vector<int>g[MAXN],Rec[MAXN];
int x,y;
int cnt_dfn;
int dep[MAXN];
int dfn[MAXN];
int Fa[MAXN];
int cnt_cycle;
vector<int>Leaf;
void dfs(int x,int f)
{
	dfn[x]=++cnt_dfn;
	 bool af=0;
	for(int i=0;i<g[x].size();i++)
	{
		int v=g[x][i];
		if(v==f)
		{
			continue;
		}
		if(dfn[v])
		{
			if(dfn[v]<dfn[x])
			{
				
			}
		}
		else
		{
			af=1;
			Fa[v]=x;
			dep[v]=dep[x]+1;
			dfs(v,x);
		}
	}
	if(!af)
	{
		Leaf.push_back(x);
		
	}
}
int main()
{
	scanf("%d %d %d",&n,&m,&k);
	for(int i=1;i<=m;i++)
	{
		scanf("%d %d",&x,&y);
		g[x].push_back(y);
		g[y].push_back(x);		
	}
	dep[1]=1;
	dfs(1,0);
	int MAXD=0;
	int cnm=0;
	for(int i=1;i<=n;i++)
	{
		if(dep[i]>MAXD)
		{
			MAXD=dep[i];
			cnm=i;
		}
	//	MAXD=max(MAXD,dep[i]);
	}
	if(MAXD>=((n%k==0)?(n/k):(n/k+1)))
	{
		printf("PATH\n");
		printf("%d\n",MAXD);
		int Now=cnm;
		while(Now)
		{
			printf("%d ",Now);
			Now=Fa[Now];
		}
	}	
	else
	{
		printf("CYCLES\n");
		for(int i=0;i<k;i++)
		{
			int x=Leaf[i];
			if(cnt_cycle!=k)
			{
				++cnt_cycle;
				int Poi=0;
				int A=g[x][Poi];
				while(A==Fa[x])
				{
					++Poi;
					A=g[x][Poi];
				}
				++Poi;
				int B=g[x][Poi];
				while(B==Fa[x])
				{
					++Poi;
					B=g[x][Poi];
				}
				int DA=(dep[x]-dep[A]+1);
				int DB=(dep[x]-dep[B]+1);
				vector<int>RRRR;
				if((DA%3==0)&&(DB%3==0))
				{
					if(dep[A]<dep[B])
					{
						swap(A,B);
					}
					RRRR.push_back(x);
					int Now=A;
					while(Now!=Fa[B])
					{
						RRRR.push_back(Now);
						Now=Fa[Now];
					}
				//	Rec[cnt_cycle]=RRRR;
				}
				
				else if((DA%3)!=0)
				{
					int Now=x;
					while(Now!=Fa[A])
					{
						RRRR.push_back(Now);
						Now=Fa[Now];
					}
			//		Rec[cnt_cycle]=RRRR;
				 } 
				 else if((DB%3)!=0)
				 {
				 	
					int Now=x;
					while(Now!=Fa[B])
					{
						RRRR.push_back(Now);
						Now=Fa[Now];
					}
				//	Rec[cnt_cycle]=RRRR;
				  } 
				  printf("%d\n",RRRR.size());
				  for(int dd=0;dd<RRRR.size();dd++)
				  {
				  	printf("%d ",RRRR[dd]);
				  }
				  printf("\n");
			}
		}
		
	}
}

CF1450E Capitalism

差分约束

主要是\(b=0\)的边

我们暂时转化为\(|a_i-a_j|\leq 1\)

这样整张图为无向图

然后先判负环

然后再判奇环(一条边相当于+1或-1,如果是奇数就无法得到原数)

这样,对于一条边的两个点\(U,V\),一定不会相同,因为如果相同,设\(d_U=d_V\),则\(dis_U+dis_V\)为偶数,边数为奇数即为奇环(负边与正边抵消)

后面就是差分约束

#include<bits/stdc++.h>
using namespace std;
const int MAXN=205;
int n;
int m;
struct Edge{
	int v;
	int val;
};
vector<Edge>g[MAXN];
int f[MAXN][MAXN];
void Add(int u,int v,int val)
{
 	Edge XN;
 	XN.v=v;
 	XN.val=val;
 	g[u].push_back(XN);
 	//f[u][v]=val;
}
int vis[MAXN];
int tot[MAXN];
int dis[MAXN];
bool spfa(int s)
{
	memset(dis,0x3f,sizeof(dis));
	memset(vis,0,sizeof(vis));
	memset(tot,0,sizeof(tot));
	dis[s]=0;
	queue<int>q;
	q.push(s);
	vis[s]=1;
	while(q.size())
	{
		int temp=q.front();
		
	 	if(tot[temp]>n)
		{
		 	return 0;	
	 	}
		tot[temp]++;
		q.pop();
		vis[temp]=0;
		for(int i=0;i<g[temp].size();i++)
		{
			int v=g[temp][i].v;
			int w=g[temp][i].val;
			if(dis[v]>dis[temp]+w)
			{
				dis[v]=dis[temp]+w;
				if(vis[v])
				{
					continue;
				 } 
				 vis[v]=1;
				 q.push(v);
				
			}
		 } 
	}
	return 1;
 } 
int x,y,z;
int Clor[MAXN];
void dfs(int x,int clor)
{
	if(Clor[x])
	{
		if(Clor[x]!=clor)
		{
			printf("NO\n");
			exit(0);
		}
		return;
	}
	Clor[x]=clor;
	for(int i=0;i<g[x].size();i++)
	{
		int v=g[x][i].v;
		dfs(v,(clor==1)?2:1);
	}
}
int main()
{
	//memset(f,0x3f,sizeof(f));
	scanf("%d %d",&n,&m);
	for(int i=1;i<=m;i++)
	{
		scanf("%d %d %d",&x,&y,&z);
		if(z==1)
		{
			Add(x,y,1);
			Add(y,x,-1);
		}
		else
		{
			Add(x,y,1);
			Add(y,x,1);
		}
	}
	for(int i=1;i<=n;i++)
	{
		if(!spfa(i))
		{
			printf("NO");
			return 0; 
		}
		else
		{
			for(int j=1;j<=n;j++)
			{
				f[i][j]=dis[j];
			}
		}
	}
	dfs(1,1); 
	int Maxi=0;
	int MMM=0;
	for(int i=1;i<=n;i++)
	{
		int Maxis=0;
		int Mini=0x3f3f3f3f;
		for(int j=1;j<=n;j++)
		{
			Maxis=max(f[i][j],Maxis);
			Mini=min(f[i][j],Mini);
		}
		int sf=Maxis-Mini;
		if(sf>Maxi){
			Maxi=sf;
			MMM=i;
		}
		for(int j=1;j<=n;j++)
		{
			f[i][j]=(f[i][j]-Mini);
		}
	}
	printf("YES\n");
	printf("%d\n",Maxi);
	for(int i=1;i<=n;i++)
	{
		printf("%d ",f[MMM][i]);
	}
}

CF1592F1 Alice and Recoloring 1

首先\((n,1)\)\((1,m)\)的操作是用不上的(\((1,1)\)的操作先覆盖\([(1,1),(x,m)]\)再覆盖\([(1,1),(x,y)]\))

设0为B,目标为全0

如果不考虑\((n,m)\)的操作

为了让花费最小,肯定一个点不会重复操作

然后判断一个点在最小的情况下是否会被覆盖

考虑二维差分(把矩阵倒着看)

\(F[i][j]=a[i+1][j]\ xor\ a[i][j+1]\ xor\ a[i+1][j+1]\)

这样修改\(F(x,y)\)等价于区间修改

然后可以确定修改的方案

最后操作四特判

#include<bits/stdc++.h>
using namespace std;
const int MAXN=505;
int n,m;
char s[MAXN];
int mp[MAXN][MAXN];
int zfx[15]={1,0,1};
int zfy[15]={0,1,1};
int NYH[MAXN][MAXN];
signed main()
{
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		scanf("%s",s+1);
		for(int j=1;j<=m;j++)
		{
			if(s[j]=='B')
			{
				mp[i][j]=1;
			}
			else
			{
				mp[i][j]=0;
			}
			NYH[i][j]=mp[i][j];
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			for(int k=0;k<3;k++)
			{
				int nx=i+zfx[k];
				int ny=j+zfy[k];
				if(nx>=1&&ny>=1&&nx<=n&&ny<=m)
				{
					NYH[i][j]^=mp[nx][ny];
				}
			}
		}
	}
	int Res=0;
	int f=0;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			Res+=NYH[i][j];
			if((NYH[i-1][j-1])&&(NYH[n][m])&&(NYH[n][j-1])&&(NYH[i-1][m]))
			{
				f=1;
			 } 
		 } 
	}
	printf("%d\n",Res-f);
}

CF1521E Nastia and a Beautiful Matrix

考虑构造成

\[\begin{matrix} ? & ? & ? &? &? \\ ? & *&?&*&? \\ ? & ? & ? &? &? \\ ? & *&?&*&? \\ ? & ? & ? &? &? \end{matrix} \quad \]

的形式,其中\((*)\)不填

观察矩阵,实际上\((*)\)就是\((i\bmod2=0,j\bmod2=0)\)的点

\((i\bmod2=1,j\bmod2=1)\)没有限制,相邻\((i+j)\bmod2=1\)的点不该相同

填色序列为每种颜色按大小排序

先填\((i\bmod 2=1,j\bmod 2=0)\),再填\((i\bmod 2=1,j\bmod 2=1)\)

最后填\((i\bmod 2=2,j\bmod 2=1)\)

我们考虑无解的情况(空格过少或每一种个数多了)

所以有解必须满足

\(n^2-(\lfloor\dfrac{n}{2}\rfloor)^2\geq m且Max\leq\dfrac{n}{2}\)

因为最大颜色的不会冲突,所以考虑填色序列相同颜色的距离一定小于\(\lfloor\dfrac{n}{2}\rfloor\)

顺序问题(感性理解就是中间有\(\lfloor\dfrac{n}{2}\rfloor\)空档)

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN=1e5+5;
int t;
int m,k;
int a[MAXN];
int Res[505][505];
pair<int,int>R[MAXN];
int zfx[15]={1,1,-1,-1};
int zfy[15]={1,-1,1,-1};
int Maxi=0;
void RR(int Mid)
{
	for(int i=1;i<=k;i++)
	{
		R[i].first=a[i];
		R[i].second=i;
	}
	sort(R+1,R+1+k);
	int poi=k;
	memset(Res,0,sizeof(Res));
	for(int i=1;i<=Mid;i++)
	{
		for(int j=1;j<=Mid;j++)
		{
			if(i&1)
			{
				if(j%2==0)
				{
					while(poi&&R[poi].first==0)
					{
						poi--;
					}
					if(!poi)
					{
						continue;
					}
					Res[i][j]=R[poi].second;
					R[poi].first--;
				}
			 } 
		}
	}
	for(int i=1;i<=Mid;i++)
	{
		for(int j=1;j<=Mid;j++)
		{
			if(i&1)
			{
				if(j&1)
				{
					while(poi&&R[poi].first==0)
					{
						poi--;
					}
					if(!poi)
					{
						continue;
					}
					Res[i][j]=R[poi].second;
					R[poi].first--;
				}
			}
		}
	}
	for(int i=1;i<=Mid;i++)
	{
		for(int j=1;j<=Mid;j++)
		{
			if(i%2==0)
			{
				if(j&1)
				{
					
					while(poi&&R[poi].first==0)
					{
						poi--;
					}
					if(!poi)
					{
						continue;
					}
					Res[i][j]=R[poi].second;
					R[poi].first--;
				}
			}
		}
	}
	while(poi&&R[poi].first==0)
	{
		poi--;
	}
	if(!poi)
	{
		return;
	}
	return; 
}
bool check(int n) {
    if((n+1)/2*n>=Maxi&&n*n-(n/2)*(n/2) >=m) {
    	return 1;
	}
	return 0;
}
signed main()
{
	scanf("%lld",&t);
	while(t--)
	{
		Maxi=0;
		scanf("%lld %lld",&m,&k);
		for(int i=1;i<=k;i++)
		{
			scanf("%lld",&a[i]);
			Maxi=max(Maxi,a[i]);
		}
		
		int l=(1);
		int r=m;
		int key;
		while(l<=r)
		{
			int mid=(l+r)>>1;
			if(check(mid)){
				key=mid;
				r=mid-1;
			}
			else
			{
				l=mid+1; 
			}
		}
		printf("%lld\n",key);
		RR(key);
		for(int i=1;i<=key;i++)
		{
			for(int j=1;j<=key;j++)
			{
				int fg=Res[i][j];
				 printf("%lld ",fg);
			}
			printf("\n");
		}

	}
}
posted @ 2022-05-12 12:00  kid_magic  阅读(29)  评论(0编辑  收藏  举报