首页 > 其他分享 >POJ 1041 John's trip

POJ 1041 John's trip

时间:2023-08-04 13:11:08浏览次数:40  
标签:1041 include int 结点 POJ 回路 John trip 欧拉

\(POJ\) \(1041\) \(John's\) \(trip\)

一、题目大意

多组数据,输入\(x,y,z\),表示结点\(x\)和结点\(y\)之间有一条序号为\(z\)的边,如果这个 无向图 中存在欧拉回路,就 输出字典序最小的欧拉回路,如果不存在欧拉回路就输出 Round trip does not exist. 。当输入0 0表示一组数据输入结束,题目保证了图的连通性。

给出一张无向图,要求从起点开始遍历一遍所有的边,最后再回到起点,题目要求输出任意一组方案

细节

  • 起点不是点\(1\),而是第一条边中两个端点中较小的一个点

  • 给出的\(x\) \(y\) \(z\)代表的是点\(x\)到点\(y\)由\(id\)为\(z\)的边连接

  • 最后答案要求输出的是边的\(id\)

二、解题思路

欧拉回路

对于一个图可以从一个顶点沿着边走下去,每个边只走一次,所有的边都经过后回到原点的路。

欧拉回路判定

  • 无向图存在欧拉回路 \(\Leftrightarrow\) 每个顶点的度是偶数
  • 有向图存在欧拉回路 \(\Leftrightarrow\) 每个顶点的出度等于入度(就是出去的边数等于进来的边数)

解题步骤

先根据欧拉路的定义判断是否存在欧拉路,如果存在的话再求字典序最小的欧拉路,一定是以边\(1\)为起始的欧拉路,然后将每个结点的边按序号从小到大排序,从而保证\(dfs\)的时候得到的是字典序最小的欧拉路。

题解:很明显的欧拉回路,首先判断是否为欧拉回路,即每个点的度都是偶数,如果满足欧拉回路,先对每个结点所连接的边按照边的编号排序,这里利用 vector 中的 pair是最好不过了.然后进行一次深搜就行了.

三、实现代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <stack>
using namespace std;
typedef pair<int, int> PII;
const int N = 5010, M = N * N * 4;
int x, y, z, start, ed, cnt;

vector<PII> g[N]; // 一维:边号;二维:节点

int d[N];       // 度
bool st[N];     // 边是不是访问过
int ans[M], al; // 欧拉路径

void dfs(int u) {
    for (int i = 0; i < g[u].size(); i++) { // 遍历u的每一条出边
        if (st[g[u][i].first]) continue;    // 如果此边已经访问过
        st[g[u][i].first] = 1;              // 标识此边已访问过
        dfs(g[u][i].second);                // 搜索下一个节点v
        ans[++al] = g[u][i].first;          // 记录边号id
    }
}
void solve() {
    for (int i = start; i <= ed; i++)
        if (d[i] & 1) { // 无向图存在欧拉回路的充要条件是每个顶点的度是偶数
            puts("Round trip does not exist.");
            return; // 本次输入处理完毕
        }

    // 对于每个节点的每条出边,按边号由小到大排序,这样可以保证最终的欧拉回路路径字典序最小
    for (int i = start; i <= ed; i++)
        sort(g[i].begin(), g[i].end());

    // 开始通过dfs搜索欧拉路径,因为起点是给定的,所以一路走回来,必然回到起点
    dfs(start);

    for (int i = al; i; i--) printf("%d ", ans[i]);
    puts("");
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("POJ1041.in", "r", stdin);
#endif

    while (true) {
        memset(g, 0, sizeof g);
        memset(d, 0, sizeof d);   // 度初始化一下
        memset(st, 0, sizeof st); // 边是否访问过的标识数组
        al = 0;                   // 清空答案数组游标

        // 本题的输入挺奇怪的,需要使用while(true)+do while的方式来读取最方便
        scanf("%d%d", &x, &y);
        if (x == 0 && y == 0) exit(0);
        // 题目中规定了这是起点:起点不是点1,而是第一条边中两个端点中较小的一个点
        start = min(x, y);
        // 最大点号,预求最大,先设最小
        ed = -1;
        do {
            scanf("%d", &z);
            ed = max(ed, max(x, y));
            d[x]++, d[y]++;
            g[x].push_back(make_pair(z, y));
            g[y].push_back(make_pair(z, x));
            scanf("%d%d", &x, &y);
        } while (x && y);
        // 封装成solve是一个好习惯
        solve();
    }
    return 0;
}

标签:1041,include,int,结点,POJ,回路,John,trip,欧拉
From: https://www.cnblogs.com/littlehb/p/17605621.html

相关文章

  • POJ 3020 Antenna Placement
    \(POJ\)\(3020\)\(Antenna\)\(Placement\)一、题目描述*--代表城市,o--代表空地给城市安装无线网,一个无线网最多可以覆盖两座城市,问覆盖所有城市最少要用多少无线。公式:最小路径覆盖=总节点数-最大匹配数我们要尽可能多的建立能覆盖两个城市的基站(二分匹配最大匹配),剩下的......
  • H - Collecting Bugs POJ-2096
    H-CollectingBugsPOJ-2096期望dp题意根据题意可以将原题意转换成:有个\(n*s\)的矩阵,每次会随机选取一个格子填上颜色,问每行每列都填上颜色的期望次数。思路dp,显然是期望dp,那么设\(dp_{i,j}\)为已经有\(i\)行\(j\)列填上颜色,到目标还需的次数的期望,那么每次......
  • POJ - Buy Tickets
    Smiling&Weeping----你看这个人,嘴里说着喜欢我却又让我这么难过DescriptionRailwayticketsweredifficulttobuyaroundtheLunarNewYearinChina,sowemustgetupearly......
  • POJ 1548 Robots
    \(POJ\)\(1548\)\(Robots\)题意相当于给出\(N\)个坐标点,因为机器人只能向下或者向右走,所以如果能到达其他点,则连接这两个点,即line[i][j]=1最小路径覆盖数:对于一个\(DAG\)(有向无环图),选取最少条路径,使得每个顶点属于且仅属于一条路径。路径长度可以为零;(有向图中找一些路径,使......
  • Gym104128L Proposition Composition
    很好口胡却不好写。把边分成链边和额外边首先想到分类讨论,显然不能只删额外边,所以有两类情况,删一链边和两链边。如果删一链边,这一链边要么完全没被额外边覆盖,然后其他任选一条;要么被覆盖一次,额外边选覆盖它的边。用线段树简单维护即可。现在难的是删两链边,且这两条链边都至少......
  • POJ1904 King's Quest
    \(POJ1904\)\(King's\)\(Quest\)一、题目描述有\(n\)个王子,每个王子都有\(k\)个喜欢的妹子,每个王子只能和喜欢的妹子结婚。现有一个匹配表,将每个王子都与一个自己喜欢的妹子配对。请你根据这个表得出每个王子可以和几个自己喜欢的妹子结婚,按序号升序输出妹子的编号,这个表应满......
  • poj 2886 Who Gets the Most Candies? (线段树单点更新应用)
                           poj2886WhoGetstheMostCandies?DescriptionNchildrenaresittinginacircletoplayagame.Thechildrenarenumberedfrom1toNinclockwiseorder.Eachofthemhasacardwithanon-zerointegeronit......
  • POJ 3694 Network
    POJ3694Network一、题目大意\(n\)个点,\(m\)个边,连通图。点与点之间通过边连接,如果切断某个边使得有点与其他点连接断开(连通分支增加),则称这种边为桥梁(离散上叫割边)。接下来有\(Q\)个操作,每操作一次,也就是切断某条边后,输出当前存在的桥梁数量。二、样例分析我们看这个4......
  • (Relax 数论1.26)POJ 1496 Word Index(计算一个字符串在字典中的位置)
    大致题意:(与POJ1850基本一致)输出某个str字符串在字典中的位置,由于字典是从a=1开始的,因此str的位置值就是在str前面所有字符串的个数+1规定输入的字符串必须是升序排列。不降序列是非法字符串要求用循环输入,输入若干组字符串,若输入非法字符串则输出0,但不结束程序,这是和POJ1850......
  • POJ 1458 Common Subsequence(动态规划)
    传送门代码如下:#include<iostream>#include<cstdio>usingnamespacestd;intmaxLen[1000][1000];intmain(){strings1,s2;while(cin>>s1>>s2){intlength1=s1.length();intlength2=s2.length();......