zoukankan      html  css  js  c++  java
  • 【拓扑排序或差分约束】Guess UVALive

    题目链接:https://cn.vjudge.net/contest/209473#problem/B

    题目大意:对于n个数字,给出sum[j]-sum[i](sum表示前缀和)的符号(正负零),求一组n个数的的可行解(n个数都在-10——10之间)【保证一定有解】

    解题思路:

    第一反应!差分约束!

    差分约束是用来求解不等式组的合理解的,用在此题上刚好,把sum[i]-sum[j]>0转化为sum[i]-sum[j]>=-1,小于零同理。把sum[i]-sum[j]==0转化为sum[i]-sum[j]>=0,sum[j]-sum[i]>=0.

    差分约束之后会在另一个专题里讲到,会此方法的同学已经可以建图跑最短路了,不会此方法的同学建议选择第二种方法拓扑排序。【但是推荐差分约束,因为感觉比拓排简单】

    后来和别的同学交流讨论,才知道这道题正解,或者说官方解是拓扑排序。

    把大小关系改成单向连边,比如本鶸的丑代码就是把大的前缀和引出一条边指向小的前缀和。

    特殊点在于等于零的处理,想了半个小时(好弱啊),想到一个很丑陋的方法,就是把两个相等的点的大小关系完全复制。也就是说如果sum[A]==sum[B],那么所有连接A却没有连接B的边,全加在B上,所有连接B没有连接A的边,全加在A上,无论方向。

    第二个特殊点在于控制n个数的大小,如果选择差分约束只需要把上限值改成10就行了,对于拓排,我就想了个丑方法,把最大的前缀和赋为10*n,往下每一层减1,由于题目保证一定有解,所以不会出现问题。

    下面放代码:

    差分约束6msAC代码:

     1 /* by Lstg */
     2 /* 2018-01-27 15:32:28 */
     3 
     4 #include<stdio.h>
     5 #define inf 102000000
     6 
     7 int map[105][105];
     8 
     9 
    10 int main(){
    11     
    12     int T,i,j,n,k;
    13     char t;
    14     scanf("%d",&T);
    15     while(T--){
    16         
    17         scanf("%d",&n);
    18         getchar();
    19         for(i=0;i<=n+1;i++)
    20             for(j=0;j<=n+1;j++)
    21                 if(i!=j)map[i][j]=inf;
    22         for(i=1;i<=n;i++)
    23             for(j=i;j<=n;j++){
    24                 t=getchar();
    25                 if(t=='+')map[j][i-1]=-1;
    26                 else if(t=='-')map[i-1][j]=-1;
    27                 else 
    28                     map[i-1][j]=map[j][i-1]=0;
    29                 
    30             }
    31         for(i=0;i<=n;i++)
    32             map[n+1][i]=10;
    33         n++;
    34         for(k=0;k<=n;k++)
    35             for(i=0;i<=n;i++)
    36                 for(j=0;j<=n;j++)
    37                     if(map[i][k]+map[k][j]<map[i][j])
    38                         map[i][j]=map[i][k]+map[k][j];
    39         for(i=1;i<n;i++)
    40             printf("%d ",map[n][i]-map[n][i-1]);
    41         putchar(10);
    42     }
    43     return 0;
    44 }

    拓扑排序6msAC代码:

     1 /* by Lstg */
     2 /* 2018-03-04 00:11:12 */
     3 
     4 
     5 #include<stdio.h>
     6 #include<string.h>
     7 
     8 int sum[105],g[105][105],du[105],stk[105],n;
     9 
    10 void _getans(){
    11     
    12     int i,top=0,p;
    13     for(i=0;i<=n;i++)
    14         if(!du[i]){
    15             stk[++top]=i;
    16             sum[i]=10*n;
    17         }
    18     while(top){
    19         p=stk[top--];
    20         for(i=0;i<=n;i++)
    21             if(g[p][i]){
    22                 du[i]--;
    23                 if(!du[i]){
    24                     sum[i]=sum[p]-1;
    25                     stk[++top]=i;
    26                 }
    27             }
    28     }
    29 }
    30 
    31 int main(){
    32 
    33     
    34     int T,i,j,k;
    35     char ch[105];
    36     
    37     scanf("%d",&T);
    38     while(T--){
    39         
    40         memset(du,0,sizeof(du));
    41         memset(g,0,sizeof(g));
    42         memset(sum,0,sizeof(sum));
    43         scanf("%d",&n);
    44         
    45         scanf("%s",ch);
    46         k=0;
    47         for(i=0;i<n;i++)
    48             for(j=i+1;j<=n;j++){
    49                 if(ch[k]=='+'){
    50                     g[j][i]=true;
    51                     du[i]++;
    52                 }
    53                 if(ch[k]=='-'){
    54                     g[i][j]=true;
    55                     du[j]++;
    56                 }
    57                 k++;
    58             }
    59         k=0;
    60         for(i=0;i<n;i++)
    61             for(j=i+1;j<=n;j++)
    62                 if(ch[k++]=='0')
    63                     for(int a=0;a<=n;a++){
    64                         if(!g[i][a]&&g[j][a]){
    65                             g[i][a]=true;
    66                             du[a]++;
    67                         }
    68                         if(!g[j][a]&&g[i][a]){
    69                             g[j][a]=true;
    70                             du[a]++;
    71                         }
    72                         if(!g[a][i]&&g[a][j]){
    73                             g[a][i]=true;
    74                             du[i]++;
    75                         }
    76                         if(!g[a][j]&&g[a][i]){
    77                             g[a][j]=true;
    78                             du[j]++;
    79                         }
    80                     }
    81         _getans();
    82         
    83         for(i=1;i<=n;i++)
    84             
    85             printf("%d ",sum[i]-sum[i-1]);
    86         putchar(10);
    87     }
    88     return 0;
    89 }        
  • 相关阅读:
    精彩分享
    Cocoa.Programming.for.Mac.OS.X 3rd 前8章小知识点
    ObjectiveC protocol 和 delegate
    Object copying
    KeyValue Observing
    实现KeyValue Coding 的5种方法
    关于 XIB 和 NIB
    ObjectiveC 中的 self 和 super
    使用KeyValue Coding
    PrepareStatement的两个executeQuery语句
  • 原文地址:https://www.cnblogs.com/L-Excalibur/p/8503602.html
Copyright © 2011-2022 走看看