zoj 2016 || poj 1386 Play on Words

    技术2024-11-08  23

    这个以前看过,没头绪,后来搜的时候,看到是欧拉路的问题。就学习了一下,也没写。

     

    网坏的时候,看了欧拉路的判断,就写了下。

     

    这题正好是判断是否是欧拉道路问题(欧拉通路或者欧拉回路),是二者其一就输出。。。possible。

     

    只需要用每个单词的首字母以及最后一个字母,然后用并查集判断是否连通,然后再用欧拉道路的判断方法即可。

     

    二者的判断方法在代码的注释中有写~排到zoj这题第一页最后一个。。真不容易。。。

     

    /* *欧拉回路,所有点连通,并且所有点的入度等于出度。 *欧拉通路。从原点S出发,经过所有点,从终点t出去。 *所有点除起点终点外的度都是偶数,且出度等于入度 *起点的出度比入度大1 *终点的入度比出度大1 */ #include <cstdio> #include <cstdlib> #include <iostream> #include <string.h> #include <queue> #include <limits.h> #define MAX 30 using namespace std; int outd[MAX]; int ind[MAX]; int pre[MAX]; int find(int x) { if( pre[x] == -1 ) pre[x] = x; while( pre[x] != x ) x = pre[x]; return x; } void Union(int x,int y) { int a = find(x); int b = find(y); if( a < b ) { pre[b] = a; pre[x] = a; pre[y] = a; } if( b < a ) { pre[a] = b; pre[x] = b; pre[y] = b; } } int check() { int a,b,i=0,k; while( pre[i] == -1 ) i++; int tmp = find(i); for(k=i+1; k<26; k++) if( pre[k] != -1 && find(k) != tmp ) return 0; return 1; } int main() { int ncases,n,len,i,sum,ans; int tmp[MAX]; char str[1010]; scanf("%d",&ncases); while( ncases-- ) { scanf("%d",&n); memset(outd,0,sizeof(outd)); memset(ind,0,sizeof(ind)); for(i=0; i<MAX; i++) pre[i] = -1; while( n-- ) { scanf("%s",str); len = strlen(str); Union(str[0]-'a',str[len-1]-'a'); outd[str[0]-'a']++; ind[str[len-1]-'a']++; } ans = check(); //判连通 if( ans == 0 ) { printf("The door cannot be opened./n"); continue; } sum = 0; for(i=0; i<26; i++) if( outd[i] != ind[i] ) tmp[sum++] = i; if( sum == 0 ) // 欧拉回路 { printf("Ordering is possible./n"); continue; } if( sum != 2 ) { printf("The door cannot be opened./n"); continue; } if( (outd[tmp[0]] - ind[tmp[0]] == 1 && outd[tmp[1]]-ind[tmp[1]] == -1) // 欧拉通路 || ( outd[tmp[0]] - ind[tmp[0]] == -1 && outd[tmp[1]]-ind[tmp[1]]) == 1 ) { printf("Ordering is possible./n"); continue; } printf("The door cannot be opened./n"); } return 0; }  

     

     

    最新回复(0)