人类智慧

赛时:

考虑 \(20pts\) 的只有 \(w=1\) 的部分分,读题可知对于 \(w=1\) 的边,它的死法有这几种:

image

注意到这个东西特别像血型但是没啥屌用,我们关注最后一个死法,即起点与终点同色。

我们注意到,对于一个有入度和出度的点,它不能当 \(D\)\(C\),而因为边的起点和终点不能同色,所以会呈现一个 \(a\to b\to a\to b\) 的样子,这简直就是告诉你它是二分图判断。(染色法)

注意到如果我们只用 \(A\)\(B\) 都能够成功完成匹配,那把能换的 \(D\)\(C\) 换了肯定不会使得无解,所以把能换的 \(D\)\(C\) 换了肯定不劣。

接下来考虑有 \(w=0\) 的情况,我们可以特判掉 \(C\)\(D\) 连向 \(A\)\(B\) 点的这种情况,然后有一个哈克:

image

然后不会了,然后写拓扑排序写爆了。

正解

拿 dfs 搞就行了,具体看代码,看不懂你是这个。👍

#include<bits/stdc++.h>
using namespace std;
namespace kong{bool st;}
namespace zhu{
//A1 B2 C3 D4
int n,m,head[100100],tot,col[100100],cnt,dflag[100100],cflag[100100],vis[100100];
int mp[5][5];
struct{
	int u,v,w;
}in[1001000];
struct{
	int nxt,to,w,fl;
}e[1001000];
void add(int u,int v,int w,int flag){
	e[++tot].to=v;
	e[tot].w=w;
	e[tot].fl=flag;
	e[tot].nxt=head[u];
	head[u]=tot;
}
bool cfs(int x){
	vis[x]=1;
	for(int i=head[x];i;i=e[i].nxt){
		int v=e[i].to;
		if(vis[v]&&cflag[v])continue;
		if(!cflag[v]||!cfs(v)){
			cflag[x]=0;
			return 0;
		}
	}
	col[x]=3;
	return 1;
}
bool dfs(int x){
	vis[x]=1;
	for(int i=head[x];i;i=e[i].nxt){
		int v=e[i].to;
		if(vis[v]&&dflag[v])continue;
		if(!dflag[v]||!dfs(v)){
			dflag[x]=0;
			return 0;
		}
	}
	col[x]=4;
	return 1;
}
bool check(int x,int c){
	col[x]=c;
	for(int i=head[x];i;i=e[i].nxt){
		int v=e[i].to;
		if(col[v]){
			if(col[v]<3&&col[v]!=((c-1)^e[i].w)+1){
				return 0;
			}
			continue;
		}
		if(!check(v,((c-1)^e[i].w)+1)){
			return 0;
		}
	}
	return 1;
}
string main(){
	cin>>n>>m;
	int cnt=0;
	for(int i=1;i<=n;i++) dflag[i]=cflag[i]=1;
	for(int i=1;i<=m;i++){
		int u,v,w;
		cin>>u>>v>>w;
		if(u==v){
			if(w!=0){
				cout<<"NO\n";
				return "我等不及了我要上厕所";
			}
			continue;
		}
		if(w==1){
			dflag[u]=cflag[v]=0;
		}
		in[++cnt]={u,v,w};
	}
	for(int i=1;i<=cnt;i++){
		if(in[i].w)continue;
		add(in[i].u,in[i].v,in[i].w,114);
	}
	for(int i=1;i<=n;i++){
		if(!col[i]&&cflag[i]){
			cfs(i);
		}
	}
	memset(head,0,sizeof head);
	tot=0;
	memset(vis,0,sizeof vis);
	for(int i=1;i<=cnt;i++){
		if(in[i].w)continue;
		add(in[i].v,in[i].u,in[i].w,514);
	}
	for(int i=1;i<=n;i++){
		if(!col[i]&&dflag[i]){
			dfs(i);
		}
	}
	memset(head,0,sizeof head);
	tot=0;
	memset(vis,0,sizeof vis);
	for(int i=1;i<=cnt;i++){
		if(!col[in[i].u]&&!col[in[i].v]){
			add(in[i].u,in[i].v,in[i].w,0);
			add(in[i].v,in[i].u,in[i].w,1);
		}
	}
	for(int i=1;i<=n;i++){
		if(!col[i]){
			if(!check(i,1)){
				cout<<"NO\n";
				return "114";
			}
		}
	}
	mp[1][4]=mp[1][2]=mp[2][4]=mp[2][1]=mp[3][4]=mp[3][1]=mp[3][2]=1;
	for(int i=1;i<=cnt;i++){
		if(mp[col[in[i].u]][col[in[i].v]]!=in[i].w){
			cout<<"NO\n";
			return "114";
		}
	}
	cout<<"YES\n";
	for(int i=1;i<=n;i++){
		cout<<(char)('A'+col[i]-1);
	}
	cout<<'\n';
	return "上厕所时不能吃东西";
}
}
namespace kong{bool ed;double MB(){return (&st-&ed)/1048576.0;}}
int main(){
	cerr<<zhu::main()<<'\n'<<kong::MB();
	return 0;
} 
posted @ 2025-07-22 15:45  LEWISAK  阅读(65)  评论(2)    收藏  举报