求调/hack
查看原帖
求调/hack
654546
qczrz6v4nhp6u楼主2023/4/18 13:56

rt,subtask4 全 WA。

思路与题解略有不同:

首先跑 Tarjan,把图变成一个 DAG。

易证把 DAG 变成全白需要操作的点是固定的(没有一个点被操作两次或以上)。

然后跑拓扑,如果当前点为黑就修改并统计需要修改的点的个数(记为 ansans)。

然后就是分类讨论。

要上课,明天回来看。

#include<bits/stdc++.h>
using namespace std;
using ll=long long;
char buf[1<<20],*p1=buf,*p2=buf;
#define getchar() (p1==p2&&(p2=buf+fread(p1=buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
template<typename T>inline void read(T& x){
    x=0;char c=getchar();bool f=0;
    for(;!isdigit(c);c=getchar())if(c=='-')f=1;
    for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+(c^48);
    f&&(x=-x);
}
template<typename T,typename... _T>inline void read(T& x,_T&... y){read(x),read(y...);}
const int N=1e5+5,M=2e5+5;
int n,m,deg[N];
int val[N],col[N];
struct edge{int x,y,z,pre;}a[M];int alen,last[N];
void ins(int x,int y,int z=0){a[++alen]={x,y,z,last[x]};last[x]=alen;}
int dfn[N],low[N];
int idx,tot;
int c[N];
int s[N],top;
bool v[N];
void dfs(int x){
    dfn[x]=low[x]=++idx;
    s[++top]=x,v[x]=1;
    for(int k=last[x];k;k=a[k].pre){
        int y=a[k].y;
        if(!dfn[y]){
            dfs(y);
            low[x]=min(low[x],low[y]);
        }
        else if(v[y])
            low[x]=min(low[x],dfn[y]);
    }
    if(low[x]==dfn[x]){
        int y;tot++;
        do{
            y=s[top--];
            v[y]=0,c[y]=tot;
        }while(y!=x);
    }
}
bool check(int x){
	if(col[c[x]]==-1)return col[c[x]]=val[x],1;
	else return col[c[x]]==val[x];
}
map<int,map<int,bool>>h;
bool Tarjan(){
	idx=0;
	tot=0;
	top=0;
	memset(dfn,0,sizeof dfn);
	memset(low,0,sizeof low);
	memset(v,0,sizeof v);
	memset(c,0,sizeof c);
	
	for(int i=1;i<=n;i++)
		if(!dfn[i])dfs(i);
	int temp=alen;
	
	alen=0,memset(last,0,sizeof last);
	memset(deg,0,sizeof deg);
	memset(col,-1,sizeof col);
	for(auto& x:h)x.second.clear();
	
	for(int i=1;i<=n;i++)
		if(!check(i))return 0;
	for(int i=1;i<=temp;i++){
		int x=a[i].x,y=a[i].y;
		if(c[x]!=c[y]&&!h[c[x]][c[y]]){
			ins(c[x],c[y]);
			h[c[x]][c[y]]=1;
			deg[c[y]]++;
		}
	}
	return 1;
}
int q[N],l,r,ans;
bool cnt[N];
void Topo(){
	l=1,r=0;
	ans=0;
	memset(cnt,0,sizeof cnt);
	for(int i=1;i<=tot;i++)
		if(!deg[i])q[++r]=i;
	while(l<=r){
		int x=q[l++];
		col[x]^=cnt[x];
		if(col[x])ans++,col[x]=0,cnt[x]^=1;
		for(int k=last[x];k;k=a[k].pre){
			int y=a[k].y;
			cnt[y]^=cnt[x];
			if(!--deg[y])q[++r]=y;
		}
	}
}
int main(){
	int t;read(t);
	while(t--){
		alen=0;
		memset(last,0,sizeof last);
		read(n,m);
		for(int i=1;i<=n;i++)read(val[i]);
		for(int i=1;i<=m;i++){
			int x,y;
			read(x,y);
			ins(x,y);
		}
		if(!Tarjan()){
			putchar('N');
			continue;
		}
		Topo();
		if(ans&1){//A不败 
			if(ans==1)putchar('A');
			else putchar('N');
		}
		else{//B不败 
			if(ans==2&&ans==tot)putchar('B');
			else if(!ans)putchar('B');
			else putchar('N');
		}
	}
}
2023/4/18 13:56
加载中...