这道题不再是差分约束的模板了(看了题解才有了思路)
首先可以根据题意知道,对于每对A、B,我们可以枚举C和D,去满足三种条件
A+B>C+D A-C>D-B 转化成差分约束的形式
然后我们可以记录maxi[i][j] 和 mini[i][j] 分别表示a[i]-a[j]的最大值和最小值
这样对于输入的四种关系可以做出如下处理
a[i]>a[j] <==> 1a[i]-a[j]2
a[i]=a[j] <==> 0a[i]-a[j]0
a[i]>a[j] <==> -2a[i]-a[j]-1
不确定a[i]、a[j]的关系 <==> -2a[i]-a[j]2
然后进行floyd
maxi[i][j]=min(maxi[i][j],maxi[i][k]+maxi[k][j]);
mini[i][j]=max(mini[i][j],mini[i][k]+mini[k][j]);
可以举个例子来说明这个关系
若i-j3 现在用k来更新这个关系 i-k<=2 k-j<=0 那么此时i-j就应更新为i-j2
即maxi[i][j]=min(maxi[i][j],maxi[i][k]+maxi[k][j])
最后进行一下判断
A+B>C+D <==>A-C>D-B 当 (A-C)min (D-B)max 或者 (A-D)min (C-B)max 时这个式子成立
同理其他的两个条件也可以推出来
附上代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=55;
int n,A,B;
int maxi[maxn][maxn],mini[maxn][maxn];
int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
scanf("%d%d%d",&n,&A,&B);
char cc[maxn];
for(int i=1;i<=n;i++)
{
scanf("%s",cc+1);
for(int j=1;j<=n;j++)
{
if(cc[j]=='?'){maxi[i][j]=2; mini[i][j]=-2; continue;}
if(cc[j]=='+'){maxi[i][j]=2; mini[i][j]=1; continue;}
if(cc[j]=='-'){maxi[i][j]=-1; mini[i][j]=-2; continue;}
if(cc[j]=='='){maxi[i][j]=0; mini[i][j]=0; continue;}
}
mini[i][i]=maxi[i][i]=0;
}
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(i!=k && j!=k && i!=j)
{
maxi[i][j]=min(maxi[i][j],maxi[i][k]+maxi[k][j]);
mini[i][j]=max(mini[i][j],mini[i][k]+mini[k][j]);
}
int c1=0,c2=0,c3=0;
for(int i=1;i<=n;i++)
{
if(i==A || i==B) continue;
for(int j=i+1;j<=n;j++)
{
if(j==A || j==B) continue;
if(mini[A][i]>maxi[j][B] || mini[A][j]>maxi[i][B]) c1++;
if((mini[A][i]==maxi[A][i] && maxi[B][j]==mini[B][j] && mini[A][i]==maxi[j][B])||(mini[A][j]==maxi[A][j] && maxi[B][i]==mini[B][i] && maxi[B][i]==mini[j][A])) c2++;
if(maxi[A][i]<mini[j][B] || maxi[A][j]<mini[i][B]) c3++;
}
}
printf("%d %d %d",c1,c2,c3);
return 0;
}