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..
*/

时间: 2024-11-05 21:55:02

POJ1128-DAG拓扑排序的相关文章

有向无环图(DAG)拓扑排序的两种方法

如下图的DAG: 第一种: (1)从AOV网中选择一个没有前驱的顶点并且输出它: (2)从AOV网中删除该顶点,并且上去所有该顶点为尾的弧: (3)重复上述两步,直到全部顶点都被输出,或者AOV网中不存在没有前驱的顶点. 第二种: 使用深度优先搜索(DFS),并标记每一个节点的第一次访问(pre)和最后一次访问时间(post),最后post的逆序就是DAG的拓扑排序,其实也是节点在进行DFS搜索时,出栈的逆序就是拓扑排序. 拓扑序列的结果有: (1) c++,高等数学,离散数学,数据结构,概率论

[POJ3249]Test for Job [拓扑排序+DAG上的最长路径]

给定一张带点权的DAG 求一条入度为0节点到出度为0节点的最长路 把点权转化为边权(同时多源转化成单源):边u->v的权值为W[v],这样入度为0的节点权值会被遗漏,新开一个点0向入度为0的点u连有向边,权值为W[u],这样就只有0是入度为0的点了. 先进行拓扑排序,再利用DAG拓扑排序后的特性求出最长路径 1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 #include &l

图的拓扑排序(转)

一.概述 对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若<u,v> ∈E(G),则u在线性序列中出现在v之前.   通常,这样的线性序列称为满足拓扑次序(TopoiSicai Order)的序列,简称拓扑序列.注意:   ①若将图中顶点按拓扑次序排成一行,则图中所有的有向边均是从左指向右的.   ②若图中存在有向环,则不可能使顶点满足拓扑次序.   ③一个DAG的拓扑序列通常表示某种方案

【luogu1137】旅行计划 [拓扑排序]

P1137 旅行计划 最长路 DAG 拓扑排序的过程中直接 DP 算是从头开始图论的学习....emmmmmmm 通常情况下,在实现的时候会维护一个队列以及每个结点的入度.在删 除边的时候顺便把相应结点的入度减去,当这个结点入度为 0 的时候直接 将其加入队列. 大概对图论形成了惯性思维 看到就怕QAQ 1 #include<iostream> 2 #include<cstdio> 3 #include<queue> 4 #include<cstring>

DAG图的拓扑排序 python

在DAG中DFS中顶点的出栈顺序即逆拓扑序. def topological_sort( graph ): is_visit = dict( ( node, False ) for node in graph ) li = [] def dfs( graph, start_node ): for end_node in graph[start_node]: if not is_visit[end_node]: is_visit[end_node] = True dfs( graph, end_n

POJ 3114 - Countries in War(强连通分量+缩点+拓扑排序+DAG最短路)

Countries in War Time Limit:1000MS    Memory Limit:65536KB    64bit IO Format:%I64d & %I64u Appoint description: Description In the year 2050, after different attempts of the UN to maintain peace in the world, the third world war broke out. The impor

poj1128拓扑排序

按照硕神的说法,以无比丑的姿势 建了个图.然后裸搞 拓扑排序 #include <cstdio> #include <cstring> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdlib> #include <list> #incl

POJ1128 Frame Stacking 【拓扑排序】+【深搜】

Frame Stacking Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 4074   Accepted: 1371 Description Consider the following 5 picture frames placed on an 9 x 8 array. ........ ........ ........ ........ .CCC.... EEEEEE.. ........ ........ ..

ACM/ICPC 之 拓扑排序+DFS(POJ1128(ZOJ1083))

经典的拓扑排序问题,难点在于字典序输出和建立拓扑图,另外理解题意是最难的难点,没有之一... POJ1128(ZOJ1083)-Frame Stacking 题意:每个图片由同一字母组成的边框表示,每个图片的字母都不同: 在一个最多30*30的区域放置这些图片,问底层向顶层叠加的图片次序,多选时按字典序输出 注:每个图片的四边都会有字符显示,其中顶点显示两边. 题解:题意的理解是难点,题目对图片的范围确定说得有点含糊不清,博主一开始就被出现的五张图片的样例迷惑,理解重心放错了.题目最需要理解的是

DAG的运用:拓扑排序(AOV),关键路径(AOE)与dp的关系

dp在DAG中有两个运用,一个是固定终点和起点的最长路(最短路) 其中最长路的算法就是关键路径(AOE)的算法. 下面是代码 #include<cstdio> #include<algorithm> #define maxn 2001 using namespace std; int a[10],head[maxn],n,p,f[maxn],tp[maxn],de[maxn],ds[maxn]; struct ss { int to,w,last; }x[maxn*1000]; v