• 排序


    链接

    https://www.acwing.com/problem/content/345/

    题目

    给定 n 个变量和 m 个不等式。其中 n 小于等于26,变量分别用前 n 的大写英文字母表示。

    不等式之间具有传递性,即若 A>B 且 B>C ,则 A>C。

    请从前往后遍历每对关系,每次遍历时判断:

    如果能够确定全部关系且无矛盾,则结束循环,输出确定的次序;
    如果发生矛盾,则结束循环,输出有矛盾;
    如果循环结束时没有发生上述两种情况,则输出无定解。
    输入格式
    输入包含多组测试数据。

    每组测试数据,第一行包含两个整数n和m。

    接下来m行,每行包含一个不等式,不等式全部为小于关系。

    当输入一行0 0时,表示输入终止。

    输出格式
    每组数据输出一个占一行的结果。

    结果可能为下列三种之一:

    如果可以确定两两之间的关系,则输出 "Sorted sequence determined after t relations: yyy...y.",其中't'指迭代次数,'yyy...y'是指升序排列的所有变量。
    如果有矛盾,则输出: "Inconsistency found after t relations.",其中't'指迭代次数。
    如果没有矛盾,且不能确定两两之间的关系,则输出 "Sorted sequence cannot be determined."。
    数据范围
    2≤n≤26,变量只可能为大写字母A~Z。

    输入样例:

    4 6
    A<B
    A<C
    B<C
    C<D
    B<D
    A<B
    3 2
    A<B
    B<A
    26 1
    A<Z
    0 0 
    

    输入样例:
    输出样例:
    输入样例:

    Sorted sequence determined after 4 relations: ABCD.
    Inconsistency found after 2 relations.
    Sorted sequence cannot be determined.
    

    思路

    传递闭包:
    由:a>b,b>c , 可知:a>c。当a到b,b到c分别有一条边时,可以向a到c连一条边。求传递闭包的过程用flody非常方便。

    在每增加一个条件时连一条边并求一次传递闭包,当有一个点可以自己走到自己,说明存在某个例子:a>b,a<b,此时无解。当每个点对之间都只存在一条边时说明已经有解。对于每个点可以被多少个点到达,就可以说明他的大小。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int N=26;
    bool g[N][N],d[N][N];
    char s[5];
    int n,m;
    int st[N];
    void flody(){
       memcpy(g,d,sizeof d);
       for(int k=0;k<n;++k){
           for(int i=0;i<n;++i){
               for(int j=0;j<n;++j){
                   g[i][j]|=g[i][k]&g[k][j];
               }
           }
       }
    }
    int  check(){  //0未确定,1得解, 2无解
       for(int i=0;i<n;++i) if(g[i][i]) return 2;
       for(int i=0;i<n;++i){
           for(int j=0;j<i;++j){
               if(!g[i][j]&&!g[j][i]) return 0;
           }
       }
       return 1;
    }
    void get_min(){
       for(int i=0;i<n;++i){
           if(st[i]) continue;
           bool flag=0;
           for(int j=0;j<n;++j){
               if(!st[j]&&g[j][i]){
                   flag=1;
                   break;
               }
           }
           if(!flag){
               cout<<(char)(i+'A');
               st[i]=1;
               return ;
           }
       }
    }
    int main(){
       while(cin>>n>>m,m||n){
           memset(st,0,sizeof st);
           memset(d,0,sizeof d);
           int type=0,t=0;
           for(int i=1;i<=m;i++){
               cin>>s;
               int x=s[0]-'A',y=s[2]-'A';
               if(!type){
                   d[x][y]=1;
                   flody();
                   type=check();
                   if(type) t=i;
               }
           }
           if(type==1){
               cout<<"Sorted sequence determined after "<<t<<" relations: ";
               int tn=n;
               while(tn--){
                   get_min();
               }
               cout<<".
    ";
           }
           else if(type==2)
               cout<<"Inconsistency found after "<<t<<" relations.
    ";
           else
               cout<<"Sorted sequence cannot be determined.
    ";
       }
       return 0;
    }
    
  • 相关阅读:
    利用libxml2解析xml文档
    找出两个链表的第一个公共结点
    [转载]风雨20年:我所积累的20条编程经验
    inotify监测文件及文件夹
    [转载]linux下svn常用指令
    利用zlib进行数据压缩
    2013腾讯编程马拉松初赛:郑厂长系列故事——体检
    Socket编程之简单介绍
    C语言中static的作用总结
    写程序实现wireshark的抓包功能
  • 原文地址:https://www.cnblogs.com/jjl0229/p/12808623.html
Copyright © 2020-2023  润新知