uva1423 巧用拓扑排序

对于一个序列 a1 a2 ... an 我们可以计算出一个符号矩阵A, 其中Si,j 为 a1+...+aj 的正负号,(连加和大于0则Sij=+ 小于0 Sij=-  等于0 则Sij=0), 根据序列A不难算出上述符号矩阵。你的任务是求解它的“逆问题” , 及给出一个符号矩阵,找出一个对应的序列。输入保证存在一个满足条件的序列,其中每个整数的绝对值均不超过10

解  连续和转化为前缀和之差,设Bi=a1+...+ai 规定B0=0 则矩阵中的任意一项都等价于连个Bi 相减之后的正负号,例如 , 第x行y列的符号为正号 ax+...+ay>0 By-Bx-1>0, 转化为已知B0,B1,...,Bn,的一些大小关系,求他们的值,这个问题通过拓扑排序完成。

#include <iostream>
#include <cstdio>
#include <string.h>
#include<vector>
#include <algorithm>
using namespace std;
const int INF=50;
char str[150];
vector<int> same[15];
vector<int> to[15];
int dgreed[15];
int G[15];
bool use[15];
int ans[15];
void solve(int loc, int v){
    for(int i=0; i<same[loc].size(); ++i)
         ans[ same[loc][i] ]=v;
}
int main()
{
     int cas;
     scanf("%d",&cas);
     for(int cc=1; cc<=cas; ++cc){
         int n;
         scanf("%d",&n);
         scanf("%s",str);
         int loc=0;
         memset(dgreed,0,sizeof(dgreed));
         memset(use,false,sizeof(use));
         for(int i=0; i<=n; ++i) to[i].clear(),ans[i]=INF,same[i].clear();
         for(int i=1; i<=n; ++i)
             for(int j=i; j<=n; ++j ){
                 if(str[loc]=='0'){
                     same[i-1].push_back(j);
                     same[j].push_back(i-1);
                 }else if(str[loc]=='+'){
                     to[i-1].push_back(j);
                     dgreed[j]++;
                 }else {
                     to[j].push_back(i-1);
                     dgreed[i-1]++;
                 }
                 loc++;
             }
          for(int i=0; i<n+1;++i){
                int k=0;
              for(int j=0; j<n+1; ++j)
                if(use[j]==false&&dgreed[j]==0){
                     k=j; break;
                }
            G[i]=k; use[k]=true;
            for(int j=0; j<to[k].size(); ++j){
                  dgreed[to[k][j]]--;
            }
          }
        loc=0;
        for(int i=0; i<n+1; ++i)
        if(G[i]==0) {
                loc=i; break;
        }
        ans[0]=0;
        int v=-1;
        solve(0,0);
        for(int i=loc-1; i>=0; --i){
              if(ans[ G[i] ] == INF){
                 ans[ G[i] ] =v--;
              }
              solve(G[i],ans[G[i]]);
        }
        v=1;
        for(int i=loc+1; i<=n; ++i){
              if(ans[ G[i] ] == INF){
                 ans[ G[i] ] =v++;
              }
              solve(G[i],ans[G[i]]);
        }
        for(int i=1; i<=n ;++i)
             printf("%d%c",ans[i]-ans[i-1],i==n?'
':' ');
     }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/Opaser/p/4284213.html