POJ 1041 John's trip(欧拉回路)
本文鏈接:http://www.cnblogs.com/Ash-ly/p/5398549.html
題意:
Johnny 有了一臺新車,他想去訪問他所有的朋友(赤裸裸的炫耀?),他的朋友有很多,住在城市中的街道上,于是他就開始規劃自己的路了,在這個城市中有很多街道,他想找一個路徑,這個路徑經過一個街道僅一次,但能訪問完他所有的朋友,他從他父母家出發,并且回來時也必須在他父母家。
在這個城市中,一共有N(N < 1995)個街道,共有M(M <= 44)個轉折點,轉折點就是一個街道的兩端,每條街道和轉折點的編號都不同。如果在一個轉折點有多種選擇,他會優先選擇街道編號比較小的。
讓你幫忙寫一個程序,找到這個路徑,如果找不到就打印“Round trip does not exist.”,從 1 號轉折點出發,最后必須回到 1 號轉折點,經過每條街道僅一次,訪問完他所有的朋友,街道是雙向的,但是不能掉頭。
思路:
把城市想象成一個圖,轉折點即是點,街道即是邊,從某一起點出發,訪問所有邊且每條邊僅訪問一次,再回到起點,很自然想到歐拉回路。首先需要判斷是否存在歐拉回路,無向圖的每個點的入度為偶數就一定存在歐拉回路。然后由于是無向圖,在存儲邊的時候需要正反各儲存一次,訪問一條邊,也要同時刪除兩條邊,正反各一條。題目還有求輸出字典序最小的,這里可以在選擇邊的時候每次選擇編號最小的那個遍歷,然后回溯回來時,也是最短的。
代碼:
/* POJ 1041 algs:鏈式前向星(存圖) + 歐拉回路(找圖) time:2016/4/25 */ #include <stdio.h> #include <string.h> #include <iostream> #include <math.h> #include <queue> #include <stack> #include <algorithm> using namespace std; int V,E; const int maxV = 44; const int maxE = 1995; int head[maxV + 7]; int visit[2 * maxE + 7]; //標志邊是否被訪問 int degree[maxV + 7]; //每個點的度 struct EdgeNode {int to;int w; //題目所給邊的編號 int next; }edges[2 * maxE + 7];int Max(int x, int y, int z){ return ( x > y ? (x > z ? x : z) : (y > z ? y : z) ) ; }int isEulur() //是否是歐拉回路 無向圖不含有度數為奇數的點 {for(int i = 1; i <= V; i++)if(degree[i] & 1) return 0;return 1; } void debugio(); void debugG(); void debugvi();stack<int> ansE;//用一個棧來存放答案 void eulurDFS(int now) {for(int i = 1; i <= degree[now]; i++) //每個點可選擇下一個擴展節點的個數 {int min = maxE + 7; //用于找到編號最小邊 int tmpvst = head[now]; //編號最小邊的下標 for(int k = head[now]; k != -1; k = edges[k].next)//在所有相鄰的邊中找編號最小邊 {if(!visit[k] && edges[k].w < min)min = edges[k].w, tmpvst = k;}if(visit[tmpvst] || min == maxE + 7) continue;visit[tmpvst] = 1; //標志找到的邊為已訪問,在鏈式前向星中每條邊被存儲了兩次 tmpvst & 1 ? visit[tmpvst + 1] = 1 : visit[tmpvst - 1] = 1;--degree[now],--degree[edges[tmpvst].to]; //訪問一條邊,則這條邊兩端點的度數各減一、否則TLE!! eulurDFS(edges[tmpvst].to);//訪問編號最小邊 ansE.push(tmpvst); //回溯的過程中記錄答案 } }int main() {//freopen("input.txt", "r", stdin);//freopen("output.txt", "w", stdout);while(true){int x, y;scanf("%d%d", &x, &y);if(!(x || y)) break;E = 0;V = 0;memset(&edges, 0, sizeof(EdgeNode));memset(head, -1, sizeof(head));memset(degree, 0, sizeof(degree));while(x || y){int z;scanf("%d", &z);++E;edges[2 * E - 1].to = y; //無向圖每條邊儲存兩次 edges[2 * E - 1].w = z;edges[2 * E - 1].next = head[x];head[x] = 2 * E - 1;edges[2 * E].to = x;edges[2 * E].w = z;edges[2 * E].next = head[y];head[y] = 2 * E;degree[x]++; //度數 degree[y]++;V = Max(V, x, y); scanf("%d%d", &x, &y);}if(isEulur()){memset(visit, 0, sizeof(visit));eulurDFS(1);int pe = 0;while(!ansE.empty()){printf( pe++ ?" %d":"%d", edges[ansE.top()].w);ansE.pop();}printf("\n");}else //不存在歐拉回路 printf("Round trip does not exist.\n");}return 0; }?
轉載于:https://www.cnblogs.com/Ash-ly/p/5398549.html
總結
以上是生活随笔為你收集整理的POJ 1041 John's trip(欧拉回路)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 对springMVC的简单理解
- 下一篇: Android—常用组件练习