题意:有n片药,有三种颜色,白色比红色重,红色比蓝色重,给你一些它们之间的重量关系,比如1>3,2=4之类,问你它们的颜色,如果没法判断的输出?。
先并查集把等于号全缩起来,然后按照大于号建图,就是一张DAG,枚举所有的点,发现它如果是一个长度为3的链的中间结点,那么它、它指向的、指向它的颜色都可以判断了。
其他的都无法判断。
#include<cstdio>
#include<cstring>
using namespace std;
int v[2][499505],nex[2][499505],first[2][1005],e[2];
void AddEdge(int U,int V,bool Type){
v[Type][++e[Type]]=V;
nex[Type][e[Type]]=first[Type][U];
first[Type][U]=e[Type];
}
int fa[1005],xs[499505],ys[499505];
char cs[499505];
int n,m;
char s[105];
int find(int x){
return x==fa[x] ? x : fa[x]=find(fa[x]);
}
int trans(int l,int r){
int res=0;
for(int i=l;i<=r;++i){
res=res*10+s[i]-'0';
}
return res;
}
char anss[1005];
int main(){
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i){
fa[i]=i;
}
for(int i=1;i<=m;++i){
scanf("%s",s);
int len=strlen(s);
for(int j=0;j<len;++j){
if(!(s[j]>='0' && s[j]<='9')){
xs[i]=trans(0,j-1);
ys[i]=trans(j+1,len-1);
cs[i]=s[j];
if(s[j]=='='){
int f1=find(xs[i]),f2=find(ys[i]);
if(f1!=f2){
fa[f1]=f2;
}
}
break;
}
}
}
for(int i=1;i<=m;++i){
if(cs[i]=='>'){
AddEdge(find(xs[i]),find(ys[i]),0);
AddEdge(find(ys[i]),find(xs[i]),1);
}
else if(cs[i]=='<'){
AddEdge(find(ys[i]),find(xs[i]),0);
AddEdge(find(xs[i]),find(ys[i]),1);
}
}
for(int i=1;i<=n;++i){
int f=find(i);
if(f!=i){
continue;
}
if(first[0][f] && first[1][f]){
anss[i]='R';
for(int j=first[0][f];j;j=nex[0][j]){
anss[v[0][j]]='B';
}
for(int j=first[1][f];j;j=nex[1][j]){
anss[v[1][j]]='W';
}
}
}
for(int i=1;i<=n;++i){
int f=find(i);
if(f!=i){
anss[i]=anss[f];
}
}
for(int i=1;i<=n;++i){
if(anss[i]!=0){
putchar(anss[i]);
}
else{
putchar('?');
}
}
puts("");
return 0;
}