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.\n",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(".\n");
48                     flag=0;
49                 }
50             }
51         }
52         if(flag) printf("Sorted sequence cannot be determined.\n");
53     }
54     return 0;
55 }
AC代码

 

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

 

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

 

posted @ 2020-11-02 21:39  dfydn  阅读(68)  评论(0编辑  收藏  举报