• 题解 P1347 【排序】


    思路

    可以将$A<B$看成$A$和$B$之间有一条权值为1有向边,那么$A-B$的值就表示为排完序后,$A$在$B$前面几位。

    然后分情况,判断结果为第1,2,3种中的哪一种。

    判断结果为第1种的方法

    如果有恰好有$(n-1)*n/2$条边没有被更新,说明结果肯定为第1种。

    为什么呢?

    因为当能将这些变量排序时,邻接矩阵的情况一定是这个亚子的:

       x1 x2 x3 x4 x5 ... xn
    x1  0  1  2  3  4 ... n-1
    x2 -1  0  1  2  3 ... n-2
    x3 -1 -1  0  1  2 ... n-3
    x4 -1 -1 -1  0  1 ... n-4
    x5 -1 -1 -1 -1  0 ... n-5
    ...
    xn -1 -1 -1 -1 -1 ... 0
    
    "-1"表示A-B之间没有边,xi表示排在第i位的变量
    

    所以没被更新的边的数量一定为$(n-1)*n/2$。

    判断结果为第2种的方法

    如果找到两个变量$A,B$,$A$在$B$前面,$B$也在$A$前面,那么这肯定矛盾了,所以结果肯定为第2种。

    判断结果为第3种的方法

    如果结果不为第1,2种,那么结果肯定为第3种。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    
    int Map[30][30];
    int ans[30];
    int n,m,flag;
    //flag=1表示结果为第1种,flag=-1表示结果为第2种,flag=0表示结果为第3种
    
    inline void get(int &u,int &v)//得到边的信息
    {
        char ch=getchar();
        while(ch>'Z'||ch<'A')
            ch=getchar();
        u=ch-'A',ch=getchar();
        while(ch>'Z'||ch<'A')
            ch=getchar();
        v=ch-'A';
    }
    
    inline void floyd(int u,int v)//将图更新
    {
        for(register int i=0;i<n;i++)
            for(register int j=0;j<n;j++)
                if(Map[i][j]<Map[i][u]+1/* 1表示u,v之间有一条权值为1的单向边 */+Map[v][j])
                    Map[i][j]=Map[i][u]+1+Map[v][j]; 
                    //如果Map[i][j]<Map[i][u]+1+Map[v][j],说明i-j之间还有u和v,于是更新Map[i][j]的值
        //这里不用单独更新u-v,当i==u,j==v时就已经更新了
    }
    
    inline void check(int now)//判断结果为第1,2,3种中的哪一种
    {
        if(flag) return;
        //判断结果是否为第2种
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                if(Map[i][j]>0&&Map[j][i]>0) flag=-1;
                //如果j在i前面且i在j前面,那么结果为第二种
        if(flag==-1){ans[0]=now;return;}
        //判断结果是否为第1种
        if(now<n-1) return;//如果操作序列次数<n-1肯定结果不为第1种
        int tot=0,p,tf;
        //tot为有多少条边还没被更新,p为在最前面的变量,tf为当前变量是否在最前面
        for(int i=0;i<n;i++){
            tf=1;
        	for(int j=0;j<n;j++)
        	    if(Map[i][j]<0) tot++,tf=0;
        	    //如果这个变量不能到达其他所有变量,那么他就不在最前面
        	if(tf) p=i;
        }
        if(tot!=(n-1)*n/2) return;
        flag=1,ans[0]=now;
        //更新ans数组
        for(int i=0;i<n;i++)
            ans[Map[p][i]+1]=i;
    }
    
    inline void print()//输出函数
    {
        if(flag){
            if(flag==1){
                printf("Sorted sequence determined after %d relations: ",ans[0]);
                for(int i=1;i<=n;i++) printf("%c",ans[i]+'A'); puts(".");
            }
            else printf("Inconsistency found after %d relations.
    ",ans[0]);
        }
        else puts("Sorted sequence cannot be determined.");
    }
    
    int main()
    {
        while(cin>>n>>m){
        	//初始化
            memset(Map,-10,sizeof Map);
            for(int i=0;i<n;i++) Map[i][i]=0;
            flag=0; 
            //输入
            int u,v;
            for(int i=1;i<=m;i++){
                get(u,v);
                floyd(u,v);
                if(flag) continue;
                check(i);
            }
            //输出
            print();
        }
        return 0;
    }
    /*
    Sorted sequence determined after () relations: ().
    Inconsistency found after () relations.
    Sorted sequence cannot be determined.
    */
    
  • 相关阅读:
    跳板机操作
    常用进制之间的转换
    vim加脚本注释和文本加密
    LAMP框架
    wiki团队协作软件Confluence
    NFS网络文件系统
    ORACLE-12C-RAC INSTALL
    通过DB_LINK按照分区表抽取数据
    Oracle Rac crs无法启动
    删除undotbs后,数据库无法启动
  • 原文地址:https://www.cnblogs.com/loafer-924/p/11925691.html
Copyright © 2020-2023  润新知