POJ:1270 Following Orders (全拓扑排序)

本文介绍了一种使用拓扑排序和全排列方法解决特定问题的算法实现。该方法适用于处理变量间的约束关系,并能够输出所有可能的字典序拓扑序列。文中提供了两种不同的实现方式,一种基于拓扑排序,另一种采用深度优先搜索(DFS)。这两种方法均能有效地解决问题,但后者在某些平台上的表现有所不同。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:第一行给出变量,第二行给出约束关系,要求按字典序输出全部拓扑序列

思路:全拓扑排序。

输入比较恶心,处理一下就可以了。

看见discuss上有人用dfs和全排列AC掉了,不得不佩服一下,这道题被我活生生做成了模版题。


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <vector>
#include <stack>
using namespace std;
typedef struct CsNode
{
    int data;
    bool vis;
    CsNode *parent,*firstchild,*nextsibling;
} CsNode,*toptree;
int n;
int in[25];
char val[25];
void process(vector<int> gl[],stack<int> &sk,int p)
{
    in[p]--;
    for(int i=0; i<gl[p].size(); ++i)
        in[gl[p][i]]--;
    for(int i=0; i<n; ++i)
        if(!in[i]) sk.push(i);
}
void addinagree(vector<int> gl[],int p)
{
    in[p]++;
    for(int i=0; i<gl[p].size(); ++i)
        in[gl[p][i]]++;
}
void createtoptree(vector<int> gl[])
{
    CsNode *head;
    head=new CsNode;
    head->data=head->vis=head->vis=head->parent=head->firstchild=head->nextsibling=NULL;
    CsNode *T;
    T=head;
    stack<int> sk;
    int cd[25]={0},cdlen=0;
    for(int i=0; i<n; ++i)
        if(!in[i]) sk.push(i);
    CsNode *p;
    while(!sk.empty())
    {
        while(!sk.empty())
        {
            while(!sk.empty())
            {
                int gettop=sk.top();
                sk.pop();
                p=new CsNode;
                p->parent=T;
                p->firstchild=NULL;
                p->data=gettop;
                p->vis=false;
                p->nextsibling=T->firstchild;
                if(p->nextsibling) p->nextsibling->parent=p;
                T->firstchild=p;
            }
            T=T->firstchild;
            int pos=T->data;
            cd[cdlen++]=pos;
            process(gl,sk,pos);
        }
        cd[cdlen]=-1;
        int k=0;
        while(cd[k]!=-1)
        {
            char c=val[cd[k]];
            printf("%c",c);
            k++;
        }
        printf("\n");
        while((p->nextsibling==0||p->vis==true)&&p->parent!=0)
        {
            if(p->vis==false)
            {
                int pos=p->data;
                addinagree(gl,pos);
                cdlen--;
            }
            p->vis=false;
            CsNode *q=p;
            p=p->parent;
            delete q;
        }
        if(p->nextsibling&&!p->vis)
        {
            p->vis=true;
            int pos=p->data;
            addinagree(gl,pos);
            cdlen--;
            T=p->nextsibling;
            pos=T->data;
            cd[cdlen++]=pos;
            process(gl,sk,pos);
        }
    }
}
int main()
{
   char  t;
    while(scanf("%c",&t)!=EOF)
    {
        vector<int> g[25];
        memset(in,0,sizeof(in));
        n=0;
        if(islower(t)) val[n++]=t;
        while(scanf("%c",&t)&&t!='\n')
            if(islower(t)) val[n++]=t;
        sort(val,val+n);
        map<char ,int> mp;
        for(int i=0; i<n; ++i)
            mp[val[i]]=i;
        int m=0;
        char a,b;
        while(scanf("%c",&t)&&t!='\n')
        {
            if(islower(t))
            {
                m++;
                if(m%2==0&&m)
                {

                    b=t;
                    int u=mp[a],v=mp[b];
                    if(g[u].end()==find(g[u].begin(),g[u].end(),v))
                    {
                        in[v]++;
                        g[u].push_back(v);
                    }
                }
                else
                    a=t;
            }
        }
        createtoptree(g);
        printf("\n");
    }
    return 0;
}


这是我后来自己写的dfs。POJ上AC了,但是UVa上WA了。。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <vector>
#define MAXN 32
using namespace std;
int n;
int in[MAXN];
int grid[MAXN][MAXN];
char lt[MAXN];
bool use[MAXN];
map<char,int> mp;
char ans[MAXN];
void dfs(int cur)
{
    if(cur==n)
        printf("%s\n",ans);
    else
    {
        for(int i=0; i<n; ++i)
            if(!in[i]&&!use[i])
            {
                use[i]=true;
                for(int j=0; j<n; ++j)
                    if(grid[i][j]==1)  in[j]--;
                ans[cur]=lt[i];
                dfs(cur+1);
                for(int j=0; j<n; ++j)
                    if(grid[i][j]==1) in[j]++;
                use[i]=false;
            }
    }
}
int main()
{
    char c;
    int kase=0;
    while(scanf("%c",&c)!=EOF)
    {

        memset(in,0,sizeof(in));
        memset(grid,0,sizeof(grid));
        memset(lt,0,sizeof(lt));
        memset(use,0,sizeof(use));
        memset(ans,0,sizeof(ans));
        mp.clear();
        n=0;
        lt[n++]=c;
        while(scanf("%c",&c)&&c!='\n')
            if(isalpha(c)) lt[n++]=c;
        sort(lt,lt+n);
        for(int i=0; i<n; ++i)
            mp[lt[i]]=i;
        char a,b;
        while(scanf("%c%c%c%c",&a,&c,&b,&c))
        {
            int x=mp[a],y=mp[b];
            grid[x][y]=1;
            in[y]++;
            if(c=='\n') break;
        }
        if(kase) printf("\n");
        dfs(0);
        kase++;
    }
    return 0;
}



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值