zoukankan      html  css  js  c++  java
  • [SCOI2008]天平 差分约束

    ~~~题面~~~

    题解:

    差分约束学得实在是太烂了,,,,QAQ

    这里先记下:

    a - b >= x  ---> a >= b + x     ---->        b ---> a = x(b连a,边权为x),      ----> 找最长路, --->f[a][b]对应a - b的最小值,

    a - b <=x ---->后面的都反过来就好了

    关于这道题:

    首先我们可以发现它实际上就是告诉了我们一堆这样的关系:

    a > b,

    a < b,

    a = b,

    所以我们应该要想到差分约束,

    如果直接连,我们发现连边权都没有,,,,

    因此我们要对式子进行转化,

    以a > b为例:

    a > b ----> a - b > 0 ---> a - b >= 1 ---> a >= b + 1,

    这就变成了形如上面的式子,

    但是我们发现我们得到了a - b 的最大值和最小值还不够,

    于是我们对目标进行转化,

    题目要求a + b  ? x + y,其中a + b给定,

    那么小于的情况实际上就是a - x < y - b || a - y < x - b,

    如果是大于,那直接换符号即可,

    如果是等于还要判断a - x的最大最小值相等,因为要确定的结果才能被计入答案,

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define R register int
      4 #define AC 52
      5 /*考虑差分约束中路的长度的意义。
      6 n很小,所以考虑floyd*/
      7 int n,a,b,ans1,ans2,ans3;
      8 int f_min[AC][AC], f_max[AC][AC];
      9 char c[AC];
     10 
     11 inline void upmin(int &a,int b)
     12 {
     13     if(b < a) a = b;
     14 }
     15 
     16 inline void upmax(int &a,int b)
     17 {
     18     if(b > a) a = b;
     19 }
     20 
     21 inline void pre()
     22 {
     23     scanf("%d%d%d",&n,&a,&b);
     24     memset(f_min,63,sizeof(f_min));
     25     for(R i=1;i<=n;i++)
     26     {
     27         scanf("%s",c+1);
     28         for(R j=1;j<=n;j++)
     29         {
     30             if(c[j] == '=' || i == j)
     31                 f_min[i][j] = f_max[i][j] = 0;
     32             else if(c[j] == '+')
     33                 f_min[i][j] = 2, f_max[i][j] = 1;//s[i] - s[j] <= 2, s[i] - s[j] >= 1(最大是3 - 1 = 2)
     34             else if(c[j] == '-')
     35                 f_min[i][j] = -1, f_max[i][j] = -2;//s[i] - s[j] <= -1, s[i] - s[j] >= -2
     36             else 
     37                 f_min[i][j] = 2, f_max[i][j] = -2;//s[i] - s[j] <= 2, i - j >= -2
     38         }
     39     }
     40 
     41 }
     42 #define f_min f_min
     43 #define f_max f_max
     44 void floyd()
     45 {
     46     /*for(R k=1;k<=n;k++)
     47         for(R i=1;i<=n;i++)
     48         {
     49             if(i == k) continue;//防止自己做中转
     50             for(R j=1;j<=n;j++)
     51             {
     52                 if(i == j) continue;//自己到自己是没有用的
     53                 upmin(f_min[i][j], f_min[i][k] + f_min[k][j]);
     54                 upmax(f_max[i][j], f_max[i][k] + f_max[k][j]);
     55             }
     56         }*/
     57     for(int k=1;k<=n;k++)            //Floyd
     58         for(int i=1;i<=n;i++) 
     59         {  
     60             if(i==k) continue;    
     61             for(int j=1;j<=n;j++)
     62             {
     63                 if(i==j) continue;
     64                 f_min[i][j]=min(f_min[i][j],f_min[i][k]+f_min[k][j]);//上界求最短路
     65                 f_max[i][j]=max(f_max[i][k]+f_max[k][j],f_max[i][j]);//下界求最长路 
     66             }
     67         }
     68 }
     69 
     70 void work()
     71 {//error!!!额。。。最长路对应最小值,最短路对应最大值
     72     /*for(R i=1;i<=n;i++)
     73     {
     74         for(R j=1;j<=n;j++)
     75             printf("%d ",f_min[i][j]);
     76         printf("
    ");
     77     }
     78     printf("
    ");
     79     for(R i=1;i<=n;i++)
     80     {
     81         for(R j=1;j<=n;j++)
     82             printf("%d ",f_max[i][j]);
     83         printf("
    ");
     84     }*/
     85     for(R i = 1; i <= n; i++)//强行枚举每一种可能
     86     {
     87         if(i == a || i == b) continue;//不能选已经选定了的
     88         for(R j = 1; j < i; j++)//<i防止重复统计
     89         {
     90             if(j == a || j == b) continue;//同上
     91             if(f_min[a][i] < f_max[j][b] || f_min[a][j] < f_max[i][b]) ++ans3;
     92             if(f_max[a][i] > f_min[j][b] || f_max[a][j] > f_min[i][b]) ++ans1;
     93             if(f_max[a][i] == f_min[a][i] && f_max[j][b] == f_min[j][b] && f_max[a][i] == f_max[j][b]) ++ans2;
     94             else if(f_min[a][j] == f_max[a][j] && f_min[i][b] == f_max[i][b] && f_min[a][j] == f_min[i][b]) ++ans2;
     95         }
     96     }
     97     printf("%d %d %d
    ",ans1,ans2,ans3);
     98 }
     99 
    100 int main()
    101 {
    102     freopen("in.in","r",stdin);
    103     pre();
    104     floyd();
    105     work();
    106     fclose(stdin);
    107     return 0;
    108 }
  • 相关阅读:
    Eclipse中创建标准web工程以及标准目录结构说明
    log4j配置说明
    常用的Eclilpse插件列表以及安装方式总结
    Eclipse插件安装总结
    eclipse中加放js文件报js语法错误解决办法
    如何在Eclipse中配置Tomcat服务器
    webpack的单vue组件(.vue)加载sass配置
    总结自己常用的几种居中方式
    两个正则坑
    CSS拾遗(二)
  • 原文地址:https://www.cnblogs.com/ww3113306/p/9158377.html
Copyright © 2011-2022 走看看