首页 > 代码库 > POJ1128-DAG拓扑排序

POJ1128-DAG拓扑排序

题目链接POJ1128

思路

如果在A的边框上出现了字母B,就说明B在A的上方

如果边框A在边框B的下方,就添加从A到B的一条有向边(题目要求从下到上输出)

那么所求的是所得有向无环图的拓扑排序

题目还要求按照字典序输出所有可能的顺序,用深度优先搜索

附代码

技术分享
#include <cstdio>
#include <cstring>
#include <vector>
#include <cmath>
#include <iostream>
#include <algorithm>
#define MAX 1000007
#define MAXN 50
#define MAXM 1007
#define INF  0x3f3f3f3f
#define NINF 0xc0c0c0c0
#define MOD 1000000007
using namespace std;
typedef long long LL;
int head[MAXN],tot,n,m,indegree[MAXN],realn;

struct Edge{
    int to;
    int next;
}edge[MAXM];

void addEdge(int u,int v){
    edge[tot].to=v;
    indegree[v]++;
    edge[tot].next=head[u];
    head[u]=tot++;
}

int visit[MAXN],Map[40][40],flag[40][40],df[MAXN];
struct Border{
    int x1,y1,x2,y2;
}border[MAXN];

int Queue[MAXN],iq;

void init(){
    tot=iq=realn=0;
    memset(head,-1,sizeof head);
    memset(visit,0,sizeof visit);
    memset(Map,0,sizeof Map);
    memset(flag,0,sizeof flag);
    memset(indegree,0,sizeof indegree);
    memset(df,0,sizeof df);
    for(int i=0;i<MAXN;i++){
        border[i].x1=border[i].y1=40;
        border[i].x2=border[i].y2=-1;
    }
}

//如果字母t在字母k的四条边框上,则连接k到t的有向边(从下到上的方向) 
void addE(int k,int x1,int y1,int x2,int y2){
    for(int i=x1;i<=x2;i++){
        for(int j=y1;j<=y2;j++){
            int t=Map[i][j];
            if(k!=t && !flag[k][t]){
                flag[k][t]=1;
                addEdge(k,t);
            }
        }
    }
}

//深度优先遍历出所有的拓扑排序 
void dfs(int now,int k){
    //cout<<now<<" "<<k<<endl;
    if(k==realn){
        for(int i=1;i<=realn;i++){
            printf("%c", Queue[i]+A-1);
        }
        printf("\n");
    }
    else{
        //删掉与now关联的边 
        for(int i=head[now];i!=-1;i=edge[i].next){
            indegree[edge[i].to]--;
        }
        //从剩余的点中选择入度为0的点,从小到大遍历 
        for(int i=1;i<MAXN;i++){
            if(!df[i]&&visit[i]&&indegree[i]==0){
                df[i]=1;
                Queue[k+1]=i;
                dfs(i,k+1);
                df[i]=0;
            }
        }
        //加回与now关联的边 
        for(int i=head[now];i!=-1;i=edge[i].next){
            indegree[edge[i].to]++;
        }
    }
}

int main(){
    char ch;
    while(scanf("%d%d",&n,&m)==2){
        init();
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                scanf(" %c",&ch);
                if(ch!=.){
                    Map[i][j]=ch-A+1;
                }
            }
        }
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                int t=Map[i][j];
                if(t){
                    visit[t]=1;
                    border[t].x1=min(border[t].x1,i);
                    border[t].y1=min(border[t].y1,j);
                    border[t].x2=max(border[t].x2,i);
                    border[t].y2=max(border[t].y2,j);
                }
            }
        }
        for(int k=1;k<30;k++){
            if(visit[k]){
                addE(k,border[k].x1,border[k].y1,border[k].x1,border[k].y2);
                addE(k,border[k].x2,border[k].y1,border[k].x2,border[k].y2);
                addE(k,border[k].x1,border[k].y1,border[k].x2,border[k].y1);
                addE(k,border[k].x1,border[k].y2,border[k].x2,border[k].y2); 
            }
        }
        //cout<<tot<<endl;
        for(int i=1;i<=30;i++){
            if(visit[i]){
                realn++;
                addEdge(0,i);
            }
        }
        //cout<<realn<<endl;
        dfs(0,0);
    }
    return 0;
}
/*
6 6
BBBCCC
BAAAAC
BABCAC
.ADDA.
.AAAA.
..DD..
*/
View Code

 

POJ1128-DAG拓扑排序