CF578E. Walking!

题目大意

题解

把一个点拆成两个点,L->R和R->L连成二分图,n-匹配数就是链数,链数-1就是答案

所以贪心匹配就行了,最后根据首尾LR情况有4种,LR和RL在存在LL或RR时都可以消掉

如果同时存在LR和RL且没有LL和RR就会挂掉,所以在找的时候优先构出LL和RR即可

这样的话就不会同时有LR和RL,因为画一下几种情况发现都会先构出LL或RR

code

#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define ll long long
//#define file
using namespace std;

int a[100001],nx[100001],d[2][2][100001],t[2][2],n,i,j,k,l,ans,s,S;
char st[100001];
bool bz[100001];

void dg(int t)
{
	printf("%d ",t),S^=1;
	if (nx[t]) dg(nx[t]);
}

int main()
{
	#ifdef file
	freopen("CF578E.in","r",stdin);
	#endif
	
	scanf("%s",st+1),n=strlen(st+1);
	fo(i,1,n) a[i]=st[i]=='R';
	fo(i,1,n)
	if (t[a[i]][a[i]^1])
	{
		nx[d[a[i]][a[i]^1][t[a[i]][a[i]^1]]]=i;
		--t[a[i]][a[i]^1];
		d[a[i]][a[i]][++t[a[i]][a[i]]]=i;
	}
	else
	if (t[a[i]^1][a[i]^1])
	{
		nx[d[a[i]^1][a[i]^1][t[a[i]^1][a[i]^1]]]=i;
		--t[a[i]^1][a[i]^1];
		d[a[i]^1][a[i]][++t[a[i]^1][a[i]]]=i;
	}
	else
	d[a[i]][a[i]][++t[a[i]][a[i]]]=i,++ans,bz[i]=1;
	
	printf("%d
",ans-1);
	memset(t,0,sizeof(t));
	fo(i,1,n)
	if (bz[i])
	{
		for (j=i; nx[j]; j=nx[j]);
		d[a[i]][a[j]][++t[a[i]][a[j]]]=i;
	}
	s=t[1][1]>t[0][0];
	while (t[0][0] || t[1][1])
	{
		if (t[0][1] || t[1][0])
		{
			if (!s)
			{while (t[0][1]) dg(d[0][1][t[0][1]]),--t[0][1];}
			else
			{while (t[1][0]) dg(d[1][0][t[1][0]]),--t[1][0];}
		}
		dg(d[s][s][t[s][s]]),--t[s][s];
		if (t[0][1] || t[1][0])
		{
			if (!s)
			{while (t[1][0]) dg(d[1][0][t[1][0]]),--t[1][0];}
			else
			{while (t[0][1]) dg(d[0][1][t[0][1]]),--t[0][1];}
		}
		s^=1;
	}
	while (t[0][1]) dg(d[0][1][t[0][1]]),--t[0][1];
	while (t[1][0]) dg(d[1][0][t[1][0]]),--t[1][0];
	printf("
");
	
	fclose(stdin);
	fclose(stdout);
	return 0;
}
原文地址:https://www.cnblogs.com/gmh77/p/13636162.html