zoukankan      html  css  js  c++  java
  • POJ 1094 Sorting It All Out (传递闭包||Floyd)

    题目链接:http://poj.org/problem?id=1094

    传递闭包:

    给定若干元素和若干对二元关系,且关系具有传递性,通过传递性推导出尽量多的元素之间的关系的问题叫做传递闭包。

    用d[i,j]=1表示i和j有关系,d[i,j]=0表示i和j没有关系。且d[i][i]始终为1。使用Floyd可以解决闭包问题。

    $ d[i,j] |= d[i,k] & d[k,j] $

    这道题从头枚举条件。每次枚举便做一次传递闭包,看:

    如果两个点之间d[i,j]=d[j,i]=1,那么是不可能的。

    如果两个点之间d[i,j]=d[j,i]=0,说明还没有确定完关系。

    如果任意i,j,只有d[i,j]=1或d[j,i]=1,那么说明是满足条件的。

    对于满足条件的,如果e[i,j]等于1,那么说明i<j,让ans[i]++,即它的优先级高,最后按ans排序,数值越大说明优先级越高。

    AC代码:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 const int N=30;
     7 char s[6];
     8 int n,m;
     9 int d[N][N],e[N][N];
    10 int floyd(){
    11     memcpy(e,d,sizeof(e));
    12     for(int k=0;k<n;k++)
    13     for(int i=0;i<n;i++)
    14     for(int j=0;j<n;j++){
    15         e[i][j]|=e[i][k]&e[k][j];
    16         if(e[i][j]==e[j][i]&&e[i][j]&&i!=j) return -1;
    17     }
    18     for(int i=0;i<n;i++)
    19     for(int j=0;j<n;j++)
    20         if(e[i][j]==e[j][i]&&!e[i][j]&&i!=j) return 0;
    21     return 1;
    22 }
    23 int main(){
    24     while(~scanf("%d%d",&n,&m)&&n){
    25         memset(d,0,sizeof(d));
    26         bool flag=1;
    27         for(int i=1;i<=m;i++){
    28             scanf("%s",s);
    29             d[s[0]-'A'][s[2]-'A']=1;
    30             if(flag){
    31                 int now=floyd();
    32                 if(now==-1){
    33                     printf("Inconsistency found after %d relations.
    ",i);
    34                     flag=0;
    35                 }
    36                 else if(now==1){
    37                     printf("Sorted sequence determined after %d relations: ", i);
    38                     pair<int,char> ans[N];
    39                     for(int j=0;j<n;j++){
    40                         ans[j].first=0;
    41                         ans[j].second='A'+j;
    42                     }
    43                     for(int j=0;j<n;j++)
    44                     for(int k=0;k<n;k++) if(e[j][k]) ans[j].first++;
    45                     sort(ans,ans+n);
    46                     for(int j=n-1;j>=0;j--) printf("%c",ans[j].second);
    47                     printf(".
    ");
    48                     flag=0;
    49                 }
    50             }
    51         }
    52         if(flag) printf("Sorted sequence cannot be determined.
    ");
    53     }
    54     return 0;
    55 }
    AC代码

    如果这道题中输入不仅有A<B的样式,还有B>A的样式,只需要在输入时做一下操作,使B>A转化成A<B即可。

    当然这道题也可以用二分来做。

  • 相关阅读:
    斐波那契数列的量化分析
    GridView编辑删除操作
    Linux crontab 命令格式与具体样例
    VB.NET版机房收费系统---组合查询
    XMLHTTP使用具体解释
    Android 在子线程中更新UI的几种方法
    国产操作系统剽窃Linux内核可耻!
    Android的PVPlayer介绍
    稀疏矩阵
    很好的理解遗传算法的样例
  • 原文地址:https://www.cnblogs.com/New-ljx/p/13916687.html
Copyright © 2011-2022 走看看