【SCOI2008】天平 [差分约束 floyd]

SCOI2008 天平

bzoj1077 luogu2447

用floyd跑差分约束==

因为砝码大小只有1、2、3 所以未知时最大差值为2 最小差值为-2

\(A+B>C+D\)可以转为\(A-C>D-B\) 然后就挨个判断就好了

注意判断等于时的条件

#include
using namespace std;
#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)<(y)?(x):(y))
const int N=50+10,M=1e6+10,inf=0x3f3f3f3f;
int n,A,B,c1,c2,c3,mx[N][N],mn[N][N];
char opt[N];

int main(){
    freopen("in.txt","r",stdin);
    scanf("%d%d%d",&n,&A,&B);
    for(int i=1;i<=n;++i){
        scanf("%s",opt+1);mx[i][i]=mn[i][i]=0;
        for(int j=1;j<=n;++j)
        if(j!=i){
            if(opt[j]=='-') mn[i][j]=-2,mx[i][j]=-1;
            else if(opt[j]=='+') mn[i][j]=1,mx[i][j]=2;
            else if(opt[j]=='=') mx[i][j]=mn[i][j]=0;
            else mn[i][j]=-2,mx[i][j]=2;
        }
    }
    for(int k=1;k<=n;++k)
        for(int i=1;i<=n;++i)
            for(int j=1;j<=n;++j)
            mn[i][j]=Max(mn[i][j],mn[i][k]+mn[k][j]),
            mx[i][j]=Min(mx[i][j],mx[i][k]+mx[k][j]);
    for(int i=1;i<=n;++i)
    if(i!=A&&i!=B)
    for(int j=i+1;j<=n;++j)
    if(j!=A&&j!=B){
        if(mn[A][i]>mx[j][B]||mn[B][i]>mx[j][A]) ++c1;
        if(mn[i][A]>mx[B][j]||mn[i][B]>mx[A][j]) ++c3;
        if(mn[A][i]==mx[A][i]&&mn[j][B]==mx[j][B]&&mn[A][i]==mn[j][B])++c2;
                else if(mn[B][i]==mx[B][i]&&mn[j][A]==mx[j][A]&&mn[B][i]==mn[j][A])++c2;
    }
    printf("%d %d %d",c1,c2,c3);
    return 0;
}

你可能感兴趣的:(【SCOI2008】天平 [差分约束 floyd])