USACO Section 3.3 Riding the Fences(歐拉路徑和歐拉回路的路徑)


Riding the Fences

Farmer John owns a large number of fences that must be repaired annually. He traverses the fences by riding a horse along each and every one of them (and nowhere else) and fixing the broken parts.

Farmer John is as lazy as the next farmer and hates to ride the same fence twice. Your program must read in a description of a network of fences and tell Farmer John a path to traverse each fence length exactly once, if possible. Farmer J can, if he wishes, start and finish at any fence intersection.

Every fence connects two fence intersections, which are numbered inclusively from 1 through 500 (though some farms have far fewer than 500 intersections). Any number of fences (>=1) can meet at a fence intersection. It is always possible to ride from any fence to any other fence (i.e., all fences are "connected").

Your program must output the path of intersections that, if interpreted as a base 500 number, would have the smallest magnitude.

There will always be at least one solution for each set of input data supplied to your program for testing.

PROGRAM NAME: fence

INPUT FORMAT

Line 1: The number of fences, F (1 <= F <= 1024)
Line 2..F+1: A pair of integers (1 <= i,j <= 500) that tell which pair of intersections this fence connects.

SAMPLE INPUT (file fence.in)

9
1 2
2 3
3 4
4 2
4 5
2 5
5 6
5 7
4 6

OUTPUT FORMAT

The output consists of F+1 lines, each containing a single integer. Print the number of the starting intersection on the first line, the next intersection's number on the next line, and so on, until the final intersection on the last line. There might be many possible answers to any given input set, but only one is ordered correctly.

SAMPLE OUTPUT (file fence.out)

1
2
3
4
2
5
4
6
5
7
題意:求歐拉圖的路徑,輸入的第一行是邊數 m ,接下來的 m 條邊,求這些邊恰好經過一次的路徑,如果存在多組解輸出字典序最小的一組。
分析:歐拉路徑和歐拉回路都有可能存在而且存在重邊,所以用鄰接矩陣存儲是刪邊時自減就行了。
fleury模板(歐拉路徑 && 歐拉回路 && 重邊)。
時間復雜度:鄰接矩陣O(n^2) 鄰接表O(e)。

View Code
/*
  ID: dizzy_l1
  LANG: C++
  TASK: fence
*/
#include<iostream>
#include<cstring>
#include<cstdio>
#include<stack>
#define MAXN 501    //頂點
#define MAXM 1030   //邊數

using namespace std;

int min_n,max_n,cnt;
int map[MAXN][MAXN],path[MAXM],degree[MAXN];
stack<int>S;

void DFS(int u)
{
    int v;
    S.push(u);
    for(v=min_n;v<=max_n;v++)
    {
        if(map[u][v])
        {
            map[u][v]--;
            map[v][u]--;
            DFS(v);
            break;
        }
    }
}

void  fleury(int u)
{
    int v;
    bool flag;
    while(!S.empty()) S.pop();
    S.push(u);
    while(!S.empty())
    {
        flag=false;
        u=S.top();S.pop();
        for(v=min_n;v<=max_n;v++)
        {
            if(map[u][v])
            {
                flag=true;
                break;
            }
        }
        if(flag)
        {
            DFS(u);
        }
        else
        {
            path[cnt++]=u;
        }
    }
}

int main()
{
    freopen("fence.in","r",stdin);
    freopen("fence.out","w",stdout);
    int m,u,v,i;
    while(scanf("%d",&m)==1)
    {
        memset(map,0,sizeof(map));
        memset(degree,0,sizeof(degree));
        min_n=520;max_n=0;
        for(i=0;i<m;i++)
        {
            scanf("%d %d",&u,&v);
            map[u][v]++;
            map[v][u]++;
            degree[u]++;
            degree[v]++;
            min_n=min(min_n,u);min_n=min(min_n,v);
            max_n=max(max_n,u);max_n=max(max_n,v);
        }
        u=520;
        for(i=min_n;i<=max_n;i++)
        {
            if(degree[i]%2==1)
                u=min(u,i);
        }
        cnt=0;
        if(u==520) fleury(min_n); //所有度為偶數
        else fleury(u);           //度有基數的
        for(i=cnt-1;i>=0;i--)
        {
            printf("%d\n",path[i]);
        }
    }
    return 0;
}

 





免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM