0
点赞
收藏
分享

微信扫一扫

poj-1386


// 1148K    360MS   G++ 

 #include <stdio.h> 

 #include <stdlib.h> 

 #include <string.h> 


 #define CHAR_NUM 26 


 char UF_array[CHAR_NUM]; 


 struct CharNodeDegree { 

     int inDegree; 

     int outDegree; 

     char used; 

 }; 


 struct InputWord { 

     int beginChar; 

     int endChar; 

 }; 


 typedef struct CharNodeDegree CharNodeDegree; 

 typedef struct InputWord InputWord; 


 CharNodeDegree nodesDegree[CHAR_NUM]; 

 InputWord inputWord[100010]; 


 #define BEGIN_CHAR 'a' 


 int UF_setNum = 0; 


 //mege child set in parent set 

 char UF_merge(int parent, int child) { 

     UF_array[child] = parent; 

     UF_setNum--; 

 } 


 char UF_getRoot(int nodeId) { 

     while(UF_array[nodeId] != nodeId) { 

         nodeId = UF_array[nodeId]; 

     } 

     return nodeId; 

 } 


 void UF_add(int from, int to) { 

 // also is a directed graph, but for connectivity check, 

 // as a undirected graph 

     if (UF_array[from] == -1 && UF_array[to] == -1) { // both belong new set 

         UF_array[to] = to; 

         UF_array[from] = to; 

         UF_setNum++; 

     } else if (UF_array[from] == -1) { // add from to 'to''s set 

         UF_array[from] = UF_getRoot(to); 

         UF_array[to] = UF_array[from]; 

     } else if (UF_array[to] == -1) { // add 'to' to from's set 

         UF_array[to] = UF_getRoot(from); 

         UF_array[from] = UF_array[to]; 

     } else { // may belong to same/different sets 

         char fromRoot = UF_getRoot(from); 

         char toRoot = UF_getRoot(to); 

         if (fromRoot != toRoot) { // belong to differents sets 

             UF_merge(fromRoot, toRoot); 

             UF_array[to] = fromRoot; 

             UF_array[from] = toRoot; 

         } 

     } 

 } 


 char existEulerPath() { 

     int OutMore1ThanTo = 0; 

     int ToMore1ThanOut = 0;; 

     for (int i = 0; i < CHAR_NUM; i++) { 

         if (nodesDegree[i].used) { 

             if (abs(nodesDegree[i].outDegree 

                     - nodesDegree[i].inDegree) > 1) { 

                 // printf("1 %d %d\n", nodesDegree[i].outDegree, nodesDegree[i].inDegree); 

                 return 0; 

             } else if (nodesDegree[i].outDegree 

                         != nodesDegree[i].inDegree) { 

                 nodesDegree[i].outDegree > nodesDegree[i].inDegree ? 

                     OutMore1ThanTo++ : ToMore1ThanOut++; 

                 if (OutMore1ThanTo > 1 || ToMore1ThanOut > 1 || (OutMore1ThanTo + ToMore1ThanOut) > 2) { 

                     // printf("2 %d %d\n", nodesDegree[i].outDegree, nodesDegree[i].inDegree); 

                     return 0; 

                 } 

             } 

         } 

     } 

     return ((OutMore1ThanTo == 1 && ToMore1ThanOut == 1) || 

         (OutMore1ThanTo == 0 && ToMore1ThanOut == 0)); 

 } 


 int main() { 


     int caseNum = 0; 

     char word[1002] = {0}; 

     scanf("%d", &caseNum); 

     for (int i = 0; i < caseNum; i++) { 

         int wordNum = 0; 

         scanf("%d", &wordNum); 

         memset(nodesDegree, 0, sizeof(nodesDegree)); 

         memset(UF_array, -1, sizeof(UF_array)); 

         memset(inputWord, 0, sizeof(inputWord)); 

         UF_setNum = 0; 

         for (int j = 0; j < wordNum; j++) { 

             scanf("%s", word); 

             int from = word[0] - BEGIN_CHAR; 

             int to = word[strlen(word)-1] - BEGIN_CHAR; 

             // UF_add(from, to); 

             nodesDegree[from].used = 1; 

             nodesDegree[to].used = 1; 

             (nodesDegree[from].outDegree)++; 

             (nodesDegree[to].inDegree)++; 

             inputWord[j].beginChar = from; 

             inputWord[j].endChar = to; 

         } 

         if (wordNum <= 1) { 

             printf("Ordering is possible.\n"); 

             continue; 

         } 

         if (existEulerPath()) { 

             // printf("connected\n"); 

             for (int i = 0; i < wordNum; i++) { 

                 UF_add(inputWord[i].beginChar, inputWord[i].endChar); 

             } 

             UF_setNum == 1 ? printf("Ordering is possible.\n") 

                             : printf("The door cannot be opened.\n"); 

         } else { 

             printf("The door cannot be opened.\n"); 

         } 

     } 
}

360MS   G++

与2513一个思路,并且因为输入的简化,因此连tire树都不需要了,趁热打铁,就当深化并查集和欧拉路,顺手解了。

这道题与2513的不同之处在于,从无向图变成了有向图(题目这次要求单词首位相接,而单词本身的排列是不能倒置的,比如,

2513 stick是没有前后的, red<-->blue 也可以看做 blue<-->red, 但这道题的单词则是分先后的, acm 就不能当 mca用,这两个完全是不同的单词),acm这个单词

只能表示从'a'到‘m’可达,但是‘m’到‘a’并不可达,因此判断欧拉路径就要按照有向图的规则:

有向图G具有 单向欧拉路,当且仅当它是连通的,而且除两个结点外,每个结点的入度等于出度,但这两个结点中,一个结点的入度比出度大1,另一个结点的入度比出度小1。
D是一个有向图,如果略去D中各有向边的方向后所得无向图G是连通图,则称D是连通图,或称D是弱连通图。

从上面两个规则看,还是之需要有并查集检查连通性然后检测每个节点的出入度就可以,因为有向图是否连通可以将其转化为相应的无向图连通,因此并查集还可以work。

然后检测出入度,要记得欧拉路径存在条件是全部的节点出度等于入度,或是一个节点 出=入+ 1, 一个节点入 = 出+1, 忘了判断全部等,WA了一次..

还有,如果先并查集检测连通,然后欧拉检测,会TLE,

因此最好先欧拉检测(时间短),如果通过,再并查集检测连通,这样能在某些欧拉都通不过的case下节省时间.



举报

相关推荐

0 条评论