ZJU 1060 Sorting It All Out - 拓扑排序

ZJU1060 PKU1094

 

题目大意:

输入n和m,表示字母表的前n个字母,总共有m组小于关系(即A < B这样的关系)。要求能否构成唯一的排序,给出的偏序关系中是否有冲突。注意,如果在第k个关系时就能确定唯一的序列,或产生冲突,那么之后输入的关系一概忽略。

 

分析:

题目的意思就是要根据这些关系确定是否存在唯一的拓扑关系。

一个很直接的思路就是,每输入一个关系,就对新的关系集合做一次拓扑排序,并判断是否存在环(冲突),是否有多个度为0的节点(排序不唯一),或排序唯一。只要检测到一次冲突或排序成功,之后的关系都不再处理。

这样做不会超时,不过我WA了若干次,最后也不知哪里错了。遂放弃这个思路。POJ的Discuss里面有很人讨论陷阱和其他一些方法,可以去参考一下。例如用BellmanFord或是传递闭包等等……

这里说一下我的解法,不用做拓扑排序

令b[i][j]表示i是否小于j。即b[i][j]==1表示已知i<j,b[i][j]==0表示不确定。

当得到一个关系x < y时:

若存在b[y][x]==1。则产生冲突。

否则,对于所有的b[i][x]==1,都赋值b[i][y]=1;对于所有的b[y][j]==1,都赋值b[x][j]=1。

这样处理之后,可以得到的b[][]数组既是已知的所有直接和间接的小于关系,判断排序成功也就容易了。

 

  1. /*
  2. ZJU1060
  3. */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <memory.h>
  7. #define clr(a) memset(a,0,sizeof(a))
  8. #define N 30
  9. int n,m;
  10. int b[N][N];
  11. int count[N];
  12. int idx[N];
  13. int ordered,conflicted;
  14. int cmp(const void *a,const void *b){
  15.     return count[*(int*)a] - count[*(int*)b];
  16. }
  17. int main()
  18. {
  19.     int i,j,k;
  20.     char s[N],x,y;
  21.     
  22.     while(scanf("%d%d",&n,&m),n+m){
  23.         //init
  24.         clr(b); clr(count);
  25.         ordered=conflicted=0;
  26.         for(i=0;i<n;i++) idx[i]=i;
  27.         //input
  28.         for(k=1;k<=m;k++){
  29.             scanf("%s",s);
  30.             if(ordered || conflicted) continue;
  31.             x=s[0]-'A'; y=s[2]-'A';
  32.             if(b[y][x]){
  33.                 conflicted=k; continue;
  34.             }
  35.             //add relation
  36.             if(b[x][y]) continue;
  37.             b[x][y]=1;
  38.             count[x]++;
  39.             for(i=0;i<n;i++){
  40.                 if(b[i][x])
  41.                     if(!b[i][y]) b[i][y]=1,count[i]++;
  42.                 if(b[y][i])
  43.                     if(!b[x][i]) b[x][i]=1,count[x]++;
  44.             }
  45.             //check ordered
  46.             qsort(idx,n,sizeof(int),cmp);
  47.             for(i=0,j=1;i<n && j;i++)
  48.                 if(count[idx[i]]!=i) j=0;
  49.             if(j) ordered=k;
  50.         }
  51.         //output
  52.         if(conflicted){
  53.             printf("Inconsistency found after %d relations./n",conflicted);
  54.         }
  55.         else if(ordered){
  56.             printf("Sorted sequence determined after %d relations: ",ordered);
  57.             for(i=n-1;i>=0;i--) printf("%c",idx[i]+'A');
  58.             printf("./n");
  59.         }
  60.         else{
  61.             puts("Sorted sequence cannot be determined.");
  62.         }
  63.     }
  64.     
  65.     return 0;
  66. }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值