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

注意到这个东西特别像血型但是没啥屌用,我们关注最后一个死法,即起点与终点同色。
我们注意到,对于一个有入度和出度的点,它不能当 \(D\) 或 \(C\),而因为边的起点和终点不能同色,所以会呈现一个 \(a\to b\to a\to b\) 的样子,这简直就是告诉你它是二分图判断。(染色法)
注意到如果我们只用 \(A\) 和 \(B\) 都能够成功完成匹配,那把能换的 \(D\) 和 \(C\) 换了肯定不会使得无解,所以把能换的 \(D\) 和 \(C\) 换了肯定不劣。
接下来考虑有 \(w=0\) 的情况,我们可以特判掉 \(C\) 和 \(D\) 连向 \(A\) 或 \(B\) 点的这种情况,然后有一个哈克:

然后不会了,然后写拓扑排序写爆了。
正解
拿 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;
}

浙公网安备 33010602011771号