• POJ题解Sorting It All Out-传递丢包+倍增


    • 题目链接:

      http://poj.org/problem?id=1094

    • 题目大意(直接从谷歌翻译上复制下来的):

      • 描述

        不同值的递增排序顺序是其中使用某种形式的小于运算符来将元素从最小到最大排序的顺序。例如,排序后的序列A,B,C,D意味着A <B,B <C和C <D.在这个问题中,我们将给出一组形式A <B的关系并要求你确定是否已排序的订单已被指定。

      • 输入

        输入由多个问题实例组成。每个实例都以包含两个正整数n和m的行开始。第一个值表示要排序的对象数量,其中2 <= n <= 26.要排序的对象将是大写字母的前n个字符。第二个值m表示将在此问题实例中给出的形式A <B的关系数目。接下来是m行,每行包含一个由三个字符组成的关系:大写字母,字符“<”和第二个大写字母。没有字母会超出字母表前n个字母的范围。 n = m = 0的值表示输入结束。

      • 输出

        对于每个问题实例,输出由一行组成。这条线应该是以下三条中的一条:

        xxx关系后确定的排序顺序:yyy ... y。
        分类序列无法确定。
        xxx关系后发现不一致。

        其中xxx是在确定排序序列或发现不一致时的处理关系数,以先到者为准,yyy ... y是已排序的递增序列。

    • 分析:

      很明显一道传递丢包的变式,怎么处理这些恼人的输出呢?虽然《算法竞赛进阶指南》说用二分,但我个人认为用倍增更好。

      首先我们用(f[x][y])表示(x>y)的关系,然后使用倍增。

      (check()==1)时说明可以判断出关系,缩短倍增长度

      (check()==2)时说明矛盾,同样缩短长度

      (check()==0)时说明判断不了全部关系,增大长度

      首先如果(check(m)==0)说明Sorted sequence cannot be determined.

      然后按照常规思维写就好了

      如果不知道常规思维怎么写就看我另一篇关于传递丢包的博客吧

    • 吐槽:

      • 辣鸡Dev Cpp

        玄学原因一直过不了样例,最后在在线IDE上一遍就过了,害我调了那么久。

      • 最近文化课压力大,好久没做OI题,感觉手感思维都有些生疏,码风比较乱。数学圆锥曲线毁我青春,作业真难做

    • 代码:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <algorithm>
    #include <cctype>
    #include <cstring>
    using namespace std;
    const int maxn=29;
    int f[maxn][maxn];
    int ans[maxn];
    int N,n,m;
    struct Relation{
    	int x,y;
    	bool bigger;
    }rel[19260817];
    char tmp[15];
    int check(int len){
    	memset(ans,0,sizeof(ans));
    	memset(f,0,sizeof(f));
    	for(register int i=1;i<=len;i++){
    		if(rel[i].bigger){
    			f[rel[i].x][rel[i].y]=1;
    		}
    		else{
    			f[rel[i].y][rel[i].x]=1;
    		}
    	}
    /*	for(register int i=0;i<n;i++){
    		for(register int j=0;j<n;j++)printf("%d",f[i][j]);
    		puts("");
    	}*/
    	for(register int k=0;k<n;k++){
    		for(register int i=0;i<n;i++){
    			for(register int j=0;j<n;j++){
    				if(i==j)continue;
    				f[i][j]|=f[i][k]&f[k][j];
    			}
    		}
    	}
    	int res=1;
    	for(register int i=0;i<n;i++){
    		int cnt=0;
    		for(register int j=0;j<n;j++){
    			if(i==j)continue;
    			if(f[i][j]&&!f[j][i]){
    				cnt++;
    			}
    			else if(f[i][j]&&f[j][i]){
    				res=2;//return 2;
    			}	
    			else if(!f[i][j]&&!f[j][i]){
    				if(res!=2)res=0;//return 0;
    			}
    		}
    		if(res==2)return 2;
    		ans[cnt+1]=i;
    	}
    	return res;
    }
    int main(){
    	while(scanf("%d %d",&n,&m)!=EOF&&(n||m)){
    		for(register int i=1;i<=m;i++){
    			scanf("%s",tmp);
    			int x=tmp[0]-'A',y=tmp[2]-'A';
    			rel[i].x=x,rel[i].y=y;
    			if(tmp[1]=='>'){
    				rel[i].bigger=1;
    			}
    			else rel[i].bigger=0;
    		}
    		if(!check(m)){
    		   puts("Sorted sequence cannot be determined.");
    		   continue;
    	    }
    		int k=0,p=1,flag;
    		while(p!=0){
    			flag=check(k+p);
    			if(!flag){
    				k+=p;
    				p=p<<1;
    			}
    			else{
    				p=p>>1;
    			}
    		    while(k+p>m)p=p>>1;
    		}
    		k++;
    		if(flag==1){//
    		   printf("Sorted sequence determined after %d relations: ",k);
    		   for(register int i=1;i<=n;i++){printf("%c",ans[i]+'A');}
    		   puts(".");
    		}
    		else if(flag==2){//mao dun
    		   printf("Inconsistency found after %d relations.
    ",k);
    		}
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    zlib 用了很多次,这次记下来
    boost 1.53 比1.52 ASIO bug 修正
    64位汇编
    js C++
    这个split 不错 我喜欢的
    布6月26日至28日将在旧金山召开2013年Build大会
    asio同步模式和异步模式
    vc6 编译boost
    windows 编译mongodb 2.4
    ajaxToolKit中 的折叠面板用法Accordion
  • 原文地址:https://www.cnblogs.com/Rye-Catcher/p/9145597.html
Copyright © 2020-2023  润新知