UVALive 4255 Guess【拓扑排序 】


题目转不过来: 点击打开链接
这个题真是万万没想到是拓扑排序啊啊啊,以为和之前有一个变换质数的题一样是深搜==挑了半天没看出来哪里错了⊙﹏⊙b汗 先说拓扑排序是什么来着,这也是扔了几乎半年的知识点==,通过找连着的边,让点的入度减少,入度为0的点入队列,从而形成一条可行路径== 这题是白书训练指南310页的例题,“连续和转化为前缀之和”这个性质我想到了,但是没想到正负号就可以确定前后两个前缀和从而在拓扑排序中建边==从大往小建边,最开始假设都是0,逐步调整s[v]=min(s[v],s[u]-1);应该是尽量让差值最小?
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int maxn=300;
    int head[maxn],ip,indegree[maxn];
    int n,m,seq[maxn];
    int s[23];
    struct note
    {
        int v,next;
    } edge[maxn*maxn];

    void init()
    {
        memset(head,-1,sizeof(head));
        ip=0;
        memset(s,0,sizeof(s));
        memset(indegree,0,sizeof(indegree));
    }

    void addedge(int u,int v)
    {
        edge[ip].v=v,edge[ip].next=head[u],head[u]=ip++;
    }

    void topo()///拓扑,可做模板
    {
        queue<int>q;
        int indeg[maxn];
        for(int i=0; i<=n; i++)
        {
            indeg[i]=indegree[i];
            if(indeg[i]==0)
                q.push(i);
        }
        int k=0;
        bool res=false;
        while(!q.empty())
        {
           // if(q.size()!=1)res=true;
            int u=q.front();
            q.pop();
          //  seq[k++]=u;
            for(int i=head[u]; i!=-1; i=edge[i].next)
            {
                int v=edge[i].v ;
                s[v]=min(s[v],s[u]-1);
                indeg[v]--;
                if(indeg[v]==0)
                {
                    q.push(v);
                }

            }
        }
//        if(k<n)return -1;///存在有向环,总之不能进行拓扑排序
//        if(res)return 0;///可以进行拓扑排序,并且只有唯一一种方式,seq数组即是排序完好的序列
//        return 1;///可以进行拓扑排序,有多种情况,seq数组是其中一种序列
    }
int main()
{
   // freopen("cin.txt","r",stdin);
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        init();
        char flag[200];
        scanf("%s",flag);
        for(int i=1,k=0;i<=n;i++)
            for(int j=i;j<=n;j++,k++)
            {
                if(flag[k] == '-')
                {
                    addedge(i-1,j);
                    indegree[j]++;
                }
                else if(flag[k] == '+')
                {
                    addedge(j,i-1);
                    indegree[i-1]++;
                }
            }
        topo();
        {
            int ans[20];
            for(int i=1;i<=n;i++)ans[i]=s[i]-s[i-1];
            for(int i=1;i<n;i++)
                printf("%d ",ans[i]);
            printf("%d\n",ans[n]);
        }

    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值