社区讨论
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 条回复,欢迎继续交流。
正在加载回复...