USACO Section 3.3 骑马修栅栏 Riding the Fences

时间:2023-03-09 04:14:01
USACO Section 3.3 骑马修栅栏 Riding the Fences

题目背景

Farmer John每年有很多栅栏要修理。他总是骑着马穿过每一个栅栏并修复它破损的地方。

题目描述

John是一个与其他农民一样懒的人。他讨厌骑马,因此从来不两次经过一个栅栏。你必须编一个程序,读入栅栏网络的描述,并计算出一条修栅栏的路径,使每个栅栏都恰好被经过一次。John能从任何一个顶点(即两个栅栏的交点)开始骑马,在任意一个顶点结束。

每一个栅栏连接两个顶点,顶点用1到500标号(虽然有的农场并没有500个顶点)。一个顶点上可连接任意多(>=1)个栅栏。两顶点间可能有多个栅栏。所有栅栏都是连通的(也就是你可以从任意一个栅栏到达另外的所有栅栏)。

你的程序必须输出骑马的路径(用路上依次经过的顶点号码表示)。我们如果把输出的路径看成是一个500进制的数,那么当存在多组解的情况下,输出500进制表示法中最小的一个 (也就是输出第一位较小的,如果还有多组解,输出第二位较小的,等等)。

输入数据保证至少有一个解。

输入输出格式

输入格式:

第1行: 一个整数F(1 <= F <= 1024),表示栅栏的数目

第2到F+1行: 每行两个整数i, j(1 <= i,j <= 500)表示这条栅栏连接i与j号顶点。

输出格式:

输出应当有F+1行,每行一个整数,依次表示路径经过的顶点号。注意数据可能有多组解,但是只有上面题目要求的那一组解是认为正确的。

求欧拉路的问题,应该先判断图中是否存在欧拉路(奇点的个数是否大于2,当然本题保证图中存在欧拉路),然后题中要求按照字典序大小来求,所以不能从任意节点出发,先判断是否存在奇点,若存在,从两个奇点中编号较小的那一个出发,若不存在,从所有节点中编号最小的一个出发。注意一点,节点的上限是500,但路径数目并没有上限(因为两个节点之间可能存在多条路径),所以存储答案的数组要足够大,只开500会WA(提交20多次就卡这一个点...)

 #include<iostream>
 #include<cstring>
 using namespace std;
 ],can[][],res[],iindex=,n,mmax=;
 void dfs(int u)
 {
      ;i<=mmax;i++)
      if(can[u][i])
      {
         can[u][i]--;
         can[i][u]--;
         dfs(i);
      }
      ++iindex;res[iindex]=u;
 }
 int main()
 {
     ,from,to;
     cin>>n;
     memset(count,,sizeof(count));
     memset(can,,sizeof(can));
     mmax=;
     while(n--)
     {
         cin>>from>>to;
         can[from][to]++;
         can[to][from]++;
         count[from]++;
         count[to]++;
         mmax=max(mmax,max(from,to));
         start=min(start,min(from,to));
     }
     ;i<=mmax;i++)
     {
           ==)
           {
                 dfs(i);
                 while(iindex)
                 cout<<res[iindex--]<<endl;
                 ;
           }
     }
     dfs(start);
     while(iindex)
         cout<<res[iindex--]<<endl;
     ;
 }