CF1634E Fair Share

CF1634E Fair Share_第1张图片
题意:有 m m m个数组,每个数组数字数量都是偶数。把每个数组对半分给集合 A 、 B A、B AB使得最终得到的可重集相同判断是否合法并且给出方案。
首先赛场上大概就只想到欧拉回路,但是因为没有拆点建图,只能做不可重集的情况,后来也就无奈下播。
做法是建立一张二部图,左部 m m m个点表示每个数组,右部 c n t cnt cnt(数字种类数)个点。
左部向右部数字 i i i的有向边表示 i i i分给 A A A集合,反之表示分给 B B B集合。容易知道原问题等价于二分图上搜欧拉回路。
然后因为也不需要输出路径,就用类似黑白染边,然后不断搜环就可。
然后搜出个环肯定不影响补图的欧拉回路性质嘛,欧拉图肯定能搜个环也是显然的,就证明完毕了。
顺便请大家欣赏一下新学的 l a m b d a lambda lambda函数

#include
#define ll long long
using namespace std;
int main()
{
	int m;
	scanf("%d",&m);
	vector<vector<int>>a(m+1),ans(m+1);
	map<int,int>mp,cnt;
	int asdf=0;
	for(int i=1;i<=m;i++)
	{
		int n;
		scanf("%d",&n);

		a[i].resize(n+1);
		ans[i].resize(n+1,-1);
		for(int j=1;j<=n;j++)
		{
			scanf("%d",&a[i][j]);
			if(mp[a[i][j]]==0)mp[a[i][j]]=++asdf;
			cnt[mp[a[i][j]]]++;
		}
	}
	for(int i=1;i<=asdf;i++)if(cnt[i]%2==1)
	{
		printf("NO");
		return 0;
	}
	vector<vector<pair<int,int>>>gra(4e5+5);
	vector<int>cur(4e5+5);
	const int MX=2e5;
	for(int i=1;i<=m;i++)
	{
		for(int j=1;j<a[i].size();j++)
		{
			gra[i].push_back({mp[a[i][j]]+MX,j});
			gra[MX+mp[a[i][j]]].push_back({i,j});
			cur[i]++;
			cur[MX+mp[a[i][j]]]++;
		}
	}
	function<void(int,int)>dfs=[&](int now,int flag)
	{
		int u=now;
		while(cur[u])
		{
			cur[u]--;
			auto [to,pos]=gra[u][cur[u]];
			while(ans[min(u,to)][pos]<0)
			{
				ans[min(u,to)][pos]=flag;
				dfs(to,1-flag);
			}
		}
	};
	for(int i=1;i<=m;i++)dfs(i,0);
	printf("YES\n");
	for(int i=1;i<=m;i++)
	{
		for(int j=1;j<ans[i].size();j++)
		{
			if(ans[i][j]==0)printf("L");
			else printf("R");
		}
		printf("\n");
	}

    return  0;
}

你可能感兴趣的:(图论,欧拉路,深度优先,图论,算法)