CSU-ACM2019暑假训练(2)

补题

原CF 1141F Graph Without Long Directed Paths

基本思路

染色问题,u和v记录边的两个顶点,dfs遍历。
有个问题是若边数=顶点数,为什么不能直接输出-1?

#include<bits/stdc++.h>
using namespace std;
typedef struct{
	vector<int>connect;
}NODE;NODE nodes[200020];
int arr[200020];
int u[200020],v[200020];
int n,m;
bool flag=true;

void dfs(int now,int pre,int precolor)
{
	arr[now]=!precolor;
	if(flag)
	{
		for(int i=0;i<nodes[now].connect.size();i++)
		{//遍历边 
			if(nodes[now].connect[i]==pre) continue;
			if(arr[nodes[now].connect[i]]==-1)
			{
				dfs(nodes[now].connect[i],now,arr[now]);
			}
			if(arr[nodes[now].connect[i]]==arr[now])
			{
				flag=false;
				return ;
			}
		}
	}
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		arr[i]=-1;
	for(int i=1;i<=m;i++)
	{
		cin>>u[i]>>v[i];
		nodes[u[i]].connect.push_back(v[i]);
		nodes[v[i]].connect.push_back(u[i]);
	}

	dfs(1,-1,0);
	if(!flag)
	{
		cout<<"NO"<<endl;
		return 0;
	}
	cout<<"YES"<<endl;
	for(int i=1;i<=m;i++)
		cout<<(arr[u[i]]==1?1:0);
	return 0;
}

原CF 1138B Circus

基本思路

若使用排列组合,会爆tle,因为maxn=5000,设A=(0,0)的个数,B=(0,1)的个数,C=(1,0)的个数,D=(1,1)的个数,则有

\[\begin{array}{l} A+B+C+D=n/2 \\ C+D=B.size()+D.size()-B-D \end{array} \]

四个未知数+两个方程组,复杂度为O(N^2),注意此题卡常,三重循环爆tle。
排列的一发tle

#include<bits/stdc++.h>
using namespace std;
typedef struct{
	int a,c;
}NODE; NODE nodes[6000];
int arr[6000];
int n;bool flag=false;
void dfs(int pos,int cnt1,int cnt2,int sum1,int sum2)
{
	if(flag)return ;
	if(cnt1==cnt2&&cnt1==n/2)
	{
		if(sum1==sum2)
		{
			for(int i=0;i<n;i++)
				if(arr[i]==1)cout<<i+1<<" ";
			flag=true;
			cout<<endl;
			return ;
		}
	}
	if(cnt1<n/2)
	{
		arr[pos]=1;
		sum1+=nodes[pos].a;
		dfs(pos+1,cnt1+1,cnt2,sum1,sum2) ;
		arr[pos]=0;
	}
	if(cnt2<n/2)
	{
		sum2+=nodes[pos].c;
		dfs(pos+1,cnt1,cnt2+1,sum1,sum2);
	}
	
} 
int main()
{
	cin>>n;
	for(int i=0;i<n;i++)
	{
		char ch;cin>>ch;if(ch=='\n')cin>>ch;
		nodes[i].a=ch-'0';
	}
	for(int i=0;i<n;i++)
	{
		char ch;cin>>ch;if(ch=='\n')cin>>ch;
		nodes[i].c=ch-'0';
	}
	dfs(0,0,0,0,0);
	if(!flag)
		cout<<-1<<endl;
	return 0;
}

AC代码

#include<bits/stdc++.h>
using namespace std;
typedef struct{
	int a,c;
}NODE; NODE nodes[6000];
int arr[6000],sum1,sum2;
vector<int>a,b,c,d;
int n;bool flag=false;
void print(int i,int j ,int k,int h)
{
	for(int x=0;x<i;x++)
	{
		cout<<a[x]<<" ";
	}
	for(int x=0;x<j;x++)
	{
		cout<<b[x]<<" ";
	}
	for(int x=0;x<k;x++)
	{
		cout<<c[x]<<" ";
	}
	for(int x=0;x<h&&x<d.size();x++)
	{
		cout<<d[x]<<" ";
	}
}
int main()
{
	cin>>n;
	for(int i=0;i<n;i++)
	{
		char ch;cin>>ch;if(ch=='\n')cin>>ch;
		nodes[i].a=ch-'0';
	}
	for(int i=0;i<n;i++)
	{
		char ch;cin>>ch;if(ch=='\n')cin>>ch;
		nodes[i].c=ch-'0';
	}
	for(int i=0;i<n;i++)
	{
		if(nodes[i].a==0)
		{
			if(nodes[i].c==0)
				a.push_back(i+1);
				else b.push_back(i+1);
		}
		else
			if(nodes[i].c==0)
				c.push_back(i+1);
			else d.push_back(i+1);
	}
	for(int i=0;i<=a.size();i++)
	{
		if(flag)break;
		for(int j=0;j<=b.size();j++)
		{
			if(flag)break;

			int k=n-2*i-j-b.size()-d.size();
			int h=b.size()+d.size()-n/2+i;
			if (h<0||h>d.size()||k<0||k>c.size()||(i+j+k+h)!=n/2)continue;
			sum1=k+h;sum2=b.size()+d.size()-j-h;
			if(sum1==sum2)
			{
				print(i,j,k,h);
				flag=true;
			}
		}
	}
	if(!flag)cout<<-1<<endl;
	return 0;
}

原CF 1152B

基本思路

位操作 \(full=2^{\log{2}{x}+1}-1\),取最前的一位0,做异或运算,每做一次操作判断是否满足条件

#include<bits/stdc++.h>
using namespace std;
int x,xx,maxbit,op=0;
vector<int>q;
int main()
{
	cin>>x;xx=x;
	int t=40;
	int full=(1<<((int)log2(x)+1))-1;
	while(t--)
	{
		maxbit=0;
		int step=0;
		if(xx==full)break;
		while(x>1)
		{
			step++;
			if((x&1)==0) maxbit=step;
			x=x>>1;
		}
		op++;
		q.push_back(maxbit);
		int y=(1<<maxbit)-1;
		xx=xx^y;
		x=xx;
		if(xx==full)break;
		while(x>1)
		{
			step++;
			if((x&1)==0) maxbit=step;
			x=x>>1;
		}
		op++;
		xx=xx+1;
		x=xx;
	}
	cout<<op<<endl;
	for(int i=0;i<q.size();i++)
		cout<<q[i]<<" ";
		
	return 0;
}
posted @ 2019-07-22 15:50  一块钱的争论  阅读(136)  评论(0编辑  收藏  举报