首先把有相等关系的都并成一个,方便讨论。
然后直接
O(n2)
暴力处理出每一个点的取值范围。
如果既有前驱又有后继,那这个点一定是2,然后暴力更新其他已知点。
未更新值的点可能有多种取值,根据连边关系限定。
然后暴力枚举C,D,以及A,B,C,D的取值,判断是否合法。以及是否答案为唯一。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
#define N 60
#define ll long long
#define inf 0x3f3f3f3f
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
int n,A,B,mp[N][N],l[N],r[N],fa[N],ans1,ans2,ans3;
char s[N][N];
inline int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
inline void merge(int x,int y){
int xx=find(x),yy=find(y);
if(xx!=yy) fa[xx]=yy;
}
int main(){
// freopen("a.in","r",stdin);
n=read();A=read();B=read();
for(int i=1;i<=n;++i) fa[i]=i;
for(int i=1;i<=n;++i){
scanf("%s",s[i]+1);
for(int j=1;j<=n;++j)
if(s[i][j]=='=') merge(i,j);
}for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
if(s[i][j]=='+') mp[find(i)][find(j)]=1,mp[find(j)][find(i)]=-1;
if(s[i][j]=='-') mp[find(i)][find(j)]=-1,mp[find(j)][find(i)]=1;
}
}for(int i=1;i<=n;++i){
if(find(i)!=i) continue;
int pre=0,succ=0;
for(int j=1;j<=n;++j) pre|=(mp[i][j]==1),succ|=(mp[i][j]==-1);
if(!pre||!succ) continue;
l[i]=2;
for(int j=1;j<=n;++j){
if(mp[i][j]==1) l[j]=1;
if(mp[i][j]==-1) l[j]=3;
}
}for(int i=1;i<=n;++i){
if(fa[i]!=i) continue;
if(l[i]){r[i]=l[i];continue;}
l[i]=1;r[i]=3;
for(int j=1;j<=n;++j){
if(mp[i][j]==1) l[i]=2;
if(mp[i][j]==-1) r[i]=2;
}
}int a=fa[A],b=fa[B];
for(int C=1;C<=n;++C){
if(C==A||C==B) continue;
for(int D=C+1;D<=n;++D){
if(D==A||D==B) continue;
int c=fa[C],d=fa[D];
int id[]={a,b,c,d},t1=0,t2=0,t3=0;
for(int vc=l[c];vc<=r[c];++vc)
for(int vd=l[d];vd<=r[d];++vd)
for(int va=l[a];va<=r[a];++va)
for(int vb=l[b];vb<=r[b];++vb){
bool flag=1;
int v[]={va,vb,vc,vd};
for(int i=0;i<4&&flag;++i)
for(int j=i+1;j<4&&flag;++j)
if(id[i]==id[j]&&v[i]!=v[j]) flag=0;
for(int i=0;i<4&&flag;++i)
for(int j=i+1;j<4&&flag;++j)
if(mp[id[i]][id[j]]==1&&v[i]<=v[j]||mp[id[i]][id[j]]==-1&&v[i]>=v[j]) flag=0;
if(!flag) continue;
if(va+vb>vc+vd) t1=1;
if(va+vb==vc+vd) t2=1;
if(va+vb<vc+vd) t3=1;
}
if(t1+t2+t3==1) ans1+=t1,ans2+=t2,ans3+=t3;
}
}printf("%d %d %d\n",ans1,ans2,ans3);
return 0;
}