zoukankan      html  css  js  c++  java
  • bzoj1077

    题解

    这道题n的范围很小,所以我们可以考虑枚举+判定 
    设放在天平右边的是C,D. 
    A+B<C+D为例,因为差分约束必须是差的形式,所以我们将式子变形 
    BC<DA然后枚举D,A的取值,就得到了一个关于两个数差的不等式。设枚举的A的值为x,那么x<=A<=x 这个式子要想转换成差分的形式,需要引入一个新变量0,设dis[0]=0,那么式子可以变成x<=A0<=x 
    注意每个点都只能从[1,3]中取值,所以隐含的限制就是1<=dis[i]dis[0]<=3。 
    题目中说只有结果保证惟一的选法才统计在内,意思是对于同一对C,D只能计算一次,且如果枚举的C,D的值不同,得到的与A+B的关系不同的话,那么方案不合法。

    代码:

    #include<bits/stdc++.h>
    const int N=100003;
    using namespace std;
    int tot,ne[N],fi[N],zz[N],c[N],mp[103][103],ans[5];
    int can[N],dis[N],n,B,A,rec[10],pd;
    void add(int x,int y,int z)
    {
        tot++;
        ne[tot]=fi[x];
        fi[x]=tot;
        zz[tot]=y;
        c[tot]=z;
    }
    void spfa(int x)
    {
        can[x]=1;
        for (int i=fi[x];i;i=ne[i])
         if (dis[zz[i]]>dis[x]+c[i])
          {
            dis[zz[i]]=dis[x]+c[i];
            if (can[zz[i]])
             {
                pd=1;
                return;
             }
            spfa(zz[i]);
            if (pd) return;
          }
        can[x]=0;
    }
    void build()
    {
        pd=0;
        for (int i=0;i<=n;i++) dis[i]=1e9,can[i]=0;
        dis[0]=0;
    }
    int check1(int c,int d,int vd,int va)
    {
        build();
        rec[0]=tot; rec[1]=fi[A]; rec[2]=fi[B]; 
        rec[3]=fi[c]; rec[4]=fi[d]; rec[5]=fi[0]; 
        int t=vd-va-1;
        add(c,B,t);
        add(0,d,vd); add(d,0,-vd);
        add(0,A,va); add(A,0,-va);
        spfa(0);
        tot=rec[0]; fi[A]=rec[1]; fi[B]=rec[2];
        fi[c]=rec[3]; fi[d]=rec[4]; fi[0]=rec[5];
        return pd;
    }
    int check2(int c,int d,int vd,int va)
    {
        build();
        rec[0]=tot; rec[1]=fi[A]; rec[2]=fi[B]; 
        rec[3]=fi[c]; rec[4]=fi[d]; rec[5]=fi[0]; 
        int t=va-vd-1;
        add(B,c,t);
        add(0,d,vd); add(d,0,-vd);
        add(0,A,va); add(A,0,-va);
        spfa(0);
        tot=rec[0]; fi[A]=rec[1]; fi[B]=rec[2];
        fi[c]=rec[3]; fi[d]=rec[4]; fi[0]=rec[5];
        return pd;
    }
    int check3(int c,int d,int vd,int va)
    {
        build();
        rec[0]=tot; rec[1]=fi[A]; rec[2]=fi[B]; 
        rec[3]=fi[c]; rec[4]=fi[d]; rec[5]=fi[0]; 
        int t=vd-va;
        add(c,B,t); add(B,c,-t);
        add(0,d,vd); add(d,0,-vd);
        add(0,A,va); add(A,0,-va);
        spfa(0);
        tot=rec[0]; fi[A]=rec[1]; fi[B]=rec[2];
        fi[c]=rec[3]; fi[d]=rec[4]; fi[0]=rec[5];
        return pd;
    }
    int main()
    {
        scanf("%d%d%d",&n,&A,&B);
        for (int i=1;i<=n;i++)
         {
            char s[100]; 
            scanf("%s",s+1);
            for (int j=1;j<=n;j++)
             {
                if (s[j]=='+') add(i,j,-1);
                if (s[j]=='-') add(j,i,-1);
                if (s[j]=='=') add(j,i,0),add(i,j,0);
             }
         }
        for (int i=1;i<=n;i++) add(0,i,3),add(i,0,-1);
        for (int i=1;i<n;i++)
         for (int j=i+1;j<=n;j++)
          {
            if (i==A||j==B||i==B||j==A) continue;
            int v1=0,v2=0,v3=0;
            for (int d=1;d<=3;d++)
             for (int a=1;a<=3;a++)
              {
                int t1=check1(i,j,d,a); 
                int t2=check2(i,j,d,a); 
                int t3=check3(i,j,d,a); 
                if (!t1) v1++;
                if (!t2) v2++;
                if (!t3) v3++;
              }
            if (v1&&!v2&&!v3) ans[1]++;
            if (!v1&&v2&&!v3) ans[2]++;
            if (!v1&&!v2&&v3) ans[3]++;
          }
        printf("%d %d %d
    ",ans[2],ans[3],ans[1]);
    }
  • 相关阅读:
    python项目_mysql开启事务
    python项目_ImageField字段
    linux基础_常用命令
    mysql数据_查询操作
    list 和 tuple——python基础学习
    python-格式化
    python-字符串
    数学——变上限积分的应用
    python-交互模式
    蓝桥杯——汉诺塔问题
  • 原文地址:https://www.cnblogs.com/xuanyiming/p/8454827.html
Copyright © 2011-2022 走看看