题 意: 思 路:先要判断连通(dfs遍历,若遍历到的节点数与输入的节点数相同说明通),这是前提条件。接着根据欧拉路径相关 定理判断。 学习点:欧拉路径 定理一、 有限图 G 是链或圈的充要条件是:G为连通图,且其中奇顶点的数目等于0或者2。有限连通图 G 是圈当且仅当它没有奇顶点; 定理二、 如果有限连通图 G 有 2k 个奇顶点,那么它可以用 k 笔画成,并且至少要用 k 笔画成。 源代码: #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXN 27 int vis[MAXN], nMap[MAXN][MAXN]; int inDegree[MAXN], outDegree[MAXN], isUsed[MAXN]; int nFlag, nNum, nCnt, nodeNum; void dfs(int u); void funcInit(); void funcInput(); void funcSolve(); void funcOutput(); int main() { int nCase; scanf("%d", &nCase); while (nCase--) { funcInit(); funcInput(); funcSolve(); funcOutput(); } return 0; } void funcInit() { int i; nodeNum = 0; nCnt = 0; nFlag = 1; memset(nMap, 0, sizeof(nMap)); for (i = 0; i != MAXN; ++i) { vis[i] = 0; inDegree[i] = 0; outDegree[i] = 0; isUsed[i] = 0; } } void funcInput() { int len, f, t; char nStr[1001]; nodeNum = 0; scanf("%d", &nNum); while (nNum--) { scanf("%s", nStr); len = strlen(nStr); f = nStr[0] - 'a'; t = nStr[len-1] - 'a'; nMap[f][t] = 1; inDegree[f] ++; outDegree[t] ++; if (!isUsed[f]) { isUsed[f] = 1; nodeNum ++; } if (!isUsed[t]) { isUsed[t] = 1; nodeNum++; } } } void funcSolve() { int i; int nIndex, ca; for (i = 0; i != MAXN; ++i) { if (!isUsed[i]) continue; break; } nCnt = 1; vis[i] = 1; dfs(i); //判断连通性! if (nCnt != nodeNum) { nFlag = 0; return; } nIndex = 0; for(i = 0; i != MAXN; ++i) { if (inDegree[i] == outDegree[i]) continue; ca = abs(inDegree[i] - outDegree[i]); if (ca == 1) { nIndex ++; if (nIndex > 2) { nFlag = 0; return; } } else if (ca > 1) { nFlag = 0; return; } } if (nIndex == 1) { nFlag = 0; } } void funcOutput() { if (nFlag) printf("Ordering is possible./n"); else printf("The door cannot be opened./n"); } void dfs(int u) { int i; for (i = 0; i < 26; ++i) { if (!vis[i] && (nMap[u][i] || nMap[i][u])) { vis[i] = 1; nCnt ++; dfs(i); } } }