社区讨论

10pts 求做法错误

P3825[NOI2017] 游戏参与者 1已保存回复 0

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
0 条
当前快照
1 份
快照标识符
@lyz28q7b
此快照首次捕获于
2024/07/24 07:42
2 年前
此快照最后确认于
2024/07/24 09:25
2 年前
查看原帖
CPP
#include<bits/stdc++.h>
using namespace std;
const int N=5e4+10,M=2e5+10;
int low[M],dfn[M],st[M],top,bel[M],tim;//TARjan 基本 
int n,d,m,len;//len无用当n 
int posx[M],cntx;//posx i  表示 第i个x赛道在原字符串下标   
// cntx 表示枚举到第几个x赛道      
char xi[M];//xi_i 表示如果原字符串s_i为x 的话 当前枚举到这个 x 变成了什么 (下标同s) 
string s;
int a1[M],b1[M];
char a2[M],b2[M];//条件 
inline int read(){
	int w=1,z=0;
	char ch=getchar();
	while(ch<'0'||ch>'9') {
		if(ch=='-') w=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9') {
		z=z*10+ch-'0';
		ch=getchar();
	}
	return z*w;
}
int head[M],idx=0;
struct edge{
	int v,next;
}e[M];
void con(int u,int v){
	e[++idx].v=v;
	e[idx].next=head[u];
	head[u]=idx;
}
int neg(int u){
	if(u>n) return u-n;
	return u+n;//取相反点 
}
int cnt;
void tj(int u){
	low[u]=dfn[u]=++tim;
	st[top++]=u;
	for(int i=head[u];i;i=e[i].next){
		int v=e[i].v;
		if(!dfn[v]){
			tj(v);
			low[u]=min(low[u],low[v]);
		}
		else if(!bel[v]){
			low[u]=min(low[u],dfn[v]);
		}
	}
	if(dfn[u]==low[u]){
		cnt++;
		while(1){
			int tem=st[--top];
			bel[tem]=cnt;
			if(u==tem)break;
		}
	}
}
int flag=0;
int pd(int i,int fl){
	if(s[i]=='a') {
		return (fl==1)?2:3;
	}
	if(s[i]=='b') {
		return (fl==1)?1:3;
	}
	if(s[i]=='c')return (fl==1)?1:2;
	if(xi[i]=='a') {
		return (fl==1)?2:3;
	}
	if(xi[i]=='b') {
		return (fl==1)?1:3;
	}
	return (fl==1)?1:2;
}// i 表示 在 s 或 xi 中的下标 ,fl表示取第几个点(赛车) (若赛道为A 第一个点为B 第二个为C ) ,而 ABC 赛车对应 123 
int lc(char x,char y){
	if(x=='a') return (y=='B')?1:2;
	if(x=='b') return (y=='A')?1:2;
	if(x=='c') return (y=='A')?1:2;
	//赛道x 当前赛车为 y ,y 是 对于 x 赛道的第几个点 
}
char tran(int x){
	if(x==1) return 'A';
	if(x==2) return 'B';
	return 'C';
	// 与pd函数连用 看pd返回值对应哪个赛车 
}
int solve(){
	for(int i=1;i<=m;i++) {
		char a=s[a1[i]],b=s[b1[i]]; //原字符串值 
		char u=xi[a1[i]],v=xi[b1[i]];//xi数组的值,某个值原串为x时就用它 
		int l=a2[i],r=b2[i];//要连的两点 
		//分类讨论 都不x 都x 一个x 共4种 
		//下列过程与题解1 类似 
		if(a!='x'&&b!='x'){
			if(a2[i]==a-32) continue;//第一个不匹配不管 
			int x=lc(a,a2[i]);//是第几辆赛车 
			if(x==2) l+=n;//赛道i i点表示第一辆赛车,i+n 表示第二辆 
			if(b2[i]==s[b1[i]]-32) {//若条件的右边不符合 
				con(l,neg(l));//表示无解 
				continue;
			}
			x=lc(s[b1[i]],b2[i]);
			if(x==2) r+=n;
			con(l,r);
			con(neg(r),neg(l));
		}
		else{
			if(a=='x'&&b=='x')
			{
				if(a2[i]==u-32) continue;//是x 就找xi数组即 (u,v) 
				int x=lc(u,a2[i]);
				if(x==2) l+=n;
				if(b2[i]==v-32) {
					con(l,neg(l));
					continue;
				}
				x=lc(v,b2[i]);
				if(x==2) r+=n;
				con(l,r);
				con(neg(r),neg(l));
			}
			else if(a!='x'){
				if(a2[i]==a-32) continue;
				int x=lc(a,a2[i]);
				if(x==2) l+=n;
				if(b2[i]==v-32) 
				{
					con(l,neg(l));
					continue;
				}
				x=lc(v,b2[i]);
				if(x==2) r+=n;
				con(l,r);
				con(neg(r),neg(l));
			}
			else{
				if(a2[i]==u-32) continue;
				int x=lc(u,a2[i]);
				if(x==2) l+=n;
				if(b2[i]==s[b1[i]]-32){
					con(l,neg(l));
					continue;
				} 
				x=lc(s[b1[i]],b2[i]);
				if(x==2) r+=n;
				
				con(l,r);
				con(neg(r),neg(l));
			}
		}
	}
	for(int i=1;i<=2*n;i++) {
		if(!dfn[i]) {
			tj(i);
		}
	}
	for(int i=1;i<=n;i++){
		if(bel[i]==bel[i+n]) return 0;
	}
	for(int i=1;i<=n;i++){
		if(bel[i]<bel[i+n]) {
			int x=pd(i,1);
			cout<<tran(x);
		}
		else{
			int x=pd(i,2);
			cout<<tran(x);
		}
	}
	return 1;
}
void clear(){
	cnt=tim=idx=0;
	memset(e,0,sizeof e);
	memset(head,0,sizeof head);
	memset(low,0,sizeof low);
	memset(dfn,0,sizeof dfn);
	memset(bel,0,sizeof bel);
}
void dfs(int u){
	if(u>d){
		clear();
		if(!flag){
			flag=solve();
		}
		return;
	}
	xi[posx[u]]='a';
	dfs(u+1);
	xi[posx[u]]='b';
	dfs(u+1);
}
signed main(){
	n=read(),d=read();
	cin>>s;
	len=s.size();
	s='*'+s;
	m=read();
	for(int i=1;i<=m;i++){
		a1[i]=read();
		cin>>a2[i];
		b1[i]=read();
		cin>>b2[i];
	}
	for(int i=1;i<=len;i++){
		if(s[i]=='x') {
			posx[++cntx]=i;
		}
	}
	dfs(1);
	if(!flag){
		puts("-1");
	}
	return 0;
}

回复

0 条回复,欢迎继续交流。

正在加载回复...