【拓扑排序或差分约束】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 }        
原文地址:https://www.cnblogs.com/L-Excalibur/p/8503602.html