POJ 1094 (传递闭包 + 拓扑排序)

题目链接: POJ 1094

题目大意:有 1 ~ N 个大写字母,且从 A 开始依次 N 个。再给你 M 个小于的关系,比如 A < B ,让你判断三种可能:

1、在第 i 个关系罗列之后,是否可以满足使得这 N 个字母能递增关系。

2、在第 i 个罗列之后,是否会出现矛盾,例如 A > B,而在第 i 个状态出现后,B > A ,故矛盾。

3、如果 M 个条件罗列完后都没有出现矛盾,且还无法判断 N 个字母的排列顺序,则输出  Sorted sequence cannot be determined.

在前两种情况中,输出最先满足的 i ,也就是说,按 m 个状态的顺序,满足任意一个条件后,其他条件都不用再判断。

思路与分析:

对于 A < B,我们建一个 A --> B 的有向图。

按 M 个状态的顺序,每次得到 A < B ,标记 a[A][B] 为 true,表示 A 能到达 B ,然后全图跑一遍 floyd 传递闭包,判断在第 i 个状态时,是否满足前两种情况。

1、在三层循环传递闭包结束后,判断图中任意两点间是否存在 A > B 且 B < A 的这种矛盾关系,即判断全图两点是否会有 a[i][j] = true 且 a[j][i] = true ,有的话,则判断为第二种情况,标记或输出当前 i 。

2、还需要判断的是,如果 a[i][j]==0 且 a[j][i]==0 ,则说明此时 i 与 j 点之间没有任何小于或大于关系,故在当前状态时,还未能判断出 N 个字母的关系。

可以先用数组存 M 个状态,或者是边输入边判断。但一定要注意的是,如果 floyd 判断为 false (即上一段中的两种情况),则还需要再判断任意两点 i j ,是否为上文中的第一种情况(即 a[i][j]==a[j][i]==true),是的话,则说明为题目所描述的第二种情况。

 

边输入边判断:

#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#define inf 0x3f3f3f3f
#define maxn 100
using namespace std;
int n,m,cnt,b,w,res;
int head[maxn],in[maxn];
bool a[maxn][maxn];
char c[maxn];
struct Edge
{
    int to;
    int next;
}edge[maxn*maxn*2];
inline void add(int u,int v)
{
    edge[++cnt].to=v;
    edge[cnt].next=head[u];
    head[u]=cnt;
    return;
}
inline bool floyd(int C)
{
    for(int k=1;k<=n;k++){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(a[i][k]&&a[k][j]) a[i][j]=true;
            }
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(i==j) continue;
            if((a[i][j]&&a[j][i])){
                b=C;
                return false;
            }
            if(a[i][j]==0&&a[j][i]==0) return false;
         }
    }
    return true;
}
void solve()
{
    queue<int> q;
    while(!q.empty()) q.pop();
    for(int i=1;i<=n;i++) {if(!in[i]) q.push(i);}
    int tot=0;
    while(!q.empty())
    {
        int x=q.front();
        q.pop();
        c[tot++]=(char)(x+‘A‘-1);
        for(int i=head[x];i;i=edge[i].next){
            int v=edge[i].to;
            in[v]--;
            if(!in[v]) q.push(v);
        }
    }
    c[tot]=‘\0‘;
    return;
}
void init()
{
    b=cnt=w=res=0;
    memset(c,0,sizeof(c));
    for(int i=1;i<=n;i++) {
        head[i]=in[i]=0;
        for(int j=1;j<=n;j++){
            a[i][j]=false;
        }
    }
}
int main()
{
    //freopen("test.in","r",stdin);
    while(~scanf("%d%d",&n,&m)){
        if(n==0&&m==0) break;
        init();
        char s[8];
        for(int i=1;i<=m;i++){
            scanf("%s",s);
            if(w||b>=inf) continue;
            int A=s[0]-‘A‘+1,B=s[2]-‘A‘+1;
            a[A][B]=true;
            add(A,B),in[B]++;
            if(floyd(inf)){
                w=1;
                if(!b) b=i;
                continue;
            }
            else{//可以不需要再进行一遍判断,只需要 floyd 保存 b 之后,最后返回即可。因为可能会先被 a[i][j]==a[j][i]==0 先返回而 b 未被赋值为 inf
                for(int k=1;k<=n;k++){
                    for(int j=1;j<=n;j++){
                        if(k==j) continue;
                        if(a[k][j]&&a[j][k]) {res=i;b=inf;}
                    }
                }
            }
        }
        if(w){
            solve();
            printf("Sorted sequence determined after %d relations: %s.\n", b,c);
        }
        else{
        if(b){printf("Inconsistency found after %d relations.\n", res);}
        else printf("Sorted sequence cannot be determined.\n");
    }
    }
}

存数组再遍历 M 个状态:

#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#define inf 0x3f3f3f3f
#define maxn 30
using namespace std;
int n,m,cnt,b,w;
int head[maxn],in[maxn];
bool a[maxn][maxn];
char c[maxn],s[1008][8];
struct Edge
{
    int to;
    int next;
}edge[maxn*maxn*2];
inline void add(int u,int v)
{
    edge[++cnt].to=v;
    edge[cnt].next=head[u];
    head[u]=cnt;
    return;
}
inline bool floyd(int C)
{
    for(int k=1;k<=n;k++){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(a[i][k]&&a[k][j]) a[i][j]=true;
            }
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(i==j) continue;
            if((a[i][j]&&a[j][i])||(a[i][j]==0&&a[j][i]==0)) return false;
    }
}
    return true;
}
void solve()
{
    queue<int> q;
    while(!q.empty()) q.pop();
    for(int i=1;i<=n;i++) {if(!in[i]) q.push(i);}
    int tot=0;
    while(!q.empty())
    {
        int x=q.front();
        q.pop();
        c[tot++]=(char)(x+‘A‘-1);
        for(int i=head[x];i;i=edge[i].next){
            int v=edge[i].to;
            in[v]--;
            if(!in[v]) q.push(v);
        }
    }
    c[tot]=‘\0‘;
    return;
}
void init()
{
    b=cnt=w=0;
    memset(c,0,sizeof(c));
    memset(s,0,sizeof(s));
    memset(a,0,sizeof(a));
    memset(head,0,sizeof(head));
}
int main()
{
    //freopen("test.in","r",stdin);
    while(~scanf("%d%d",&n,&m)){
        if(n==0&&m==0) break;
        init();
        for(int i=1;i<=m;i++){
            scanf("%s",s[i]);
        }
        for(int i=1;i<=m;i++){
            int A=s[i][0]-‘A‘+1,B=s[i][2]-‘A‘+1;
            a[A][B]=true;
            if(floyd()){
                for(int j=1;j<=i;j++){
                    A=s[j][0]-‘A‘+1,B=s[j][2]-‘A‘+1;
                    add(A,B),in[B]++;
                }
                solve();
                printf("Sorted sequence determined after %d relations: %s.\n",i,c);
                w=1;
            }
            else{
                for(int k=1;k<=n;k++){
                    for(int j=1;j<=n;j++){
                        if(k==j) continue;
                        if(a[k][j]&&a[j][k]){
                            printf("Inconsistency found after %d relations.\n", i);
                            w=1;
                            break;
                        }
                        if(w) break;
                    }
                }
            }
            if(w) break;
        }
        if(!w) printf("Sorted sequence cannot be determined.\n");
    }
}

原文地址:https://www.cnblogs.com/Absofuckinglutely/p/11396070.html

时间: 2024-10-12 03:48:31

POJ 1094 (传递闭包 + 拓扑排序)的相关文章

POJ 1094 Sorting It All Out【floyd传递闭包+拓扑排序】

Sorting It All Out Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 31994 Accepted: 11117 Description An ascending sorted sequence of distinct values is one in which some form of a less-than operator is used to order the elements from small

Genealogical tree POJ 2367【拓扑排序】

http://poj.org/problem?id=2367 Genealogical tree Special Judge Problem Description The system of Martians' blood relations is confusing enough. Actually, Martians bud when they want and where they want. They gather together in different groups, so th

【POJ 2186】拓扑排序

题意 给出n,代表有以A开始的n个字母,给出它们的m个小于关系(A<B).如果前i个关系可以确定n个字母的一个顺序就输出: Sorted sequence determined after i relations: 排好的字母. 如果前i个关系开始导致矛盾,就输出: Inconsistency found after i relations. m个关系后还不能确定顺序就输出: Sorted sequence cannot be determined. 代码 /* g[i][j]为邻接矩阵,e[i

Poj 1094 拓扑排序 水题

Sad..这么水的题WA了无数发,题目要看仔细啊,留下来做个警告把 #include <cstdio> #include <cstring> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdlib> #include <list> #i

【POJ】1094 Sorting It All Out(拓扑排序)

http://poj.org/problem?id=1094 原来拓扑序可以这样做,原来一直sb的用白书上说的dfs............ 拓扑序只要每次将入度为0的点加入栈,然后每次拓展维护入度即可.. 我是个大sb,这种水题调了一早上.. #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include &

poj 1094 拓扑排序

Description An ascending sorted sequence of distinct values is one in which some form of a less-than operator is used to order the elements from smallest to largest. For example, the sorted sequence A, B, C, D implies that A < B, B < C and C < D.

[ACM] POJ 1094 Sorting It All Out (拓扑排序)

Sorting It All Out Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 26801   Accepted: 9248 Description An ascending sorted sequence of distinct values is one in which some form of a less-than operator is used to order the elements from sm

poj 1094 Sorting It All Out (拓扑排序)

Sorting It All Out Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 27929   Accepted: 9655 Description An ascending sorted sequence of distinct values is one in which some form of a less-than operator is used to order the elements from sm

POJ 1094 Sorting It All Out(拓扑排序&#183;判断+实现)

题意  由一些不同元素组成的升序序列是可以用若干个小于号将所有的元素按从小到大的顺序 排列起来的序列.例如,排序后的序列为 A, B, C, D,这意味着 A < B.B < C和C < D.在本题中, 给定一组形如 A < B的关系式,你的任务是判定是否存在一个有序序列. 输出到哪一项可以确定顺序或者在这一项最先出现冲突,若所有的小于关系都处理完了都不能确定顺序也没有出现冲突,就输出不能确定 每来一个小于关系就进行一次拓扑排序  直到出现冲突(也就是出现了环)或者已经能确定顺序