CCF-CSP题解 201512-4 送货

求字典序最小欧拉路。

似乎不能用\(Fluery\)算法(\(O(E^2)\))。\(Fluery\)算法的思路是:延申的边尽可能不是除去已走过边的图的桥(割)。每走一步都要判断是否是割,应当会超时。

采用\(Hierholzer\)算法(\(O(V+E)\)),亦称逐步插入回路法。思路见代码。注意根据题意,每次选取未走过顶点最小的边延申。

注意题目要求从1号节点出发。

欧拉路存在的条件:

无向图:

存在欧拉回路的条件:原图连通,每个节点均为偶度节点。

存在欧拉通路的条件:存在欧拉回路,或原图连通,有两个节点为奇度节点,其他节点均为偶度节点。

有向图:

存在欧拉回路的条件:基图(有向边变成无向边)连通,每个节点的入度等于出度。

存在欧拉通路的条件:存在欧拉回路,或基图连通,有一个节点入度等于出度+1,有一个节点出度等于入度+1,其他节点入度等于出度。

#include<bits/stdc++.h>
const int maxn = 10000;
const int maxm = 100000;

using namespace std;

int to[maxm * 2 + 10];
int vis[maxm * 2 + 10];
int nex[maxm * 2 + 10];
int head[maxn + 10], cnt = 0;

void addEdge(int a, int b)
{
    to[cnt] = b;
    vis[cnt] = 0;
    nex[cnt] = head[a];
    head[a] = cnt++;
    to[cnt] = a;
    vis[cnt] = 0;
    nex[cnt] = head[b];
    head[b] = cnt++;
}

int degree[maxn + 10];

int vis1[maxn + 10], num = 0;

void dfs(int x)
{
    vis1[x] = 1;
    num++;
    for (int i = head[x]; i != -1; i = nex[i])
    {
        int l = to[i];
        if (!vis1[l])
            dfs(l);
    }
}

int main()
{
    int n, m;
    scanf("%d%d", &n, &m);

    memset(head, -1, sizeof(head));
    memset(degree, 0, sizeof(degree));
    for (int i = 1, a, b; i <= m; i++)
    {
        scanf("%d%d", &a, &b);
        addEdge(a, b);
        degree[a]++;
        degree[b]++;
    }

    memset(vis1, 0, sizeof(vis1));
    dfs(1);

    int odd = 0;
    for (int i = 1; i <= n; i++)
    {
        if (degree[i] % 2)
            odd++;
    }

    if (num == n && (odd == 0 || (odd == 2 && degree[1] % 2)))
    {
        stack<int> s1, s2;
        s1.push(1);
        while (!s1.empty())
        {
            int x = s1.top();
            int y = -1, ii = -1;
            for (int i = head[x]; i != -1; i = nex[i])
            {
                if (vis[i])
                    continue;
                int l = to[i];
                if (y == -1 || y > l)
                    y = l, ii = i;
            }
            if (y == -1)
            {
                s2.push(x);
                s1.pop();
            }
            else
            {
                vis[ii] = vis[ii ^ 1] = 1;
                s1.push(y);
            }
        }
        bool first = true;
        while (!s2.empty())
        {
            if (first)
            {
                printf("%d", s2.top());
                s2.pop();
                first = false;
            }
            else
            {
                printf(" %d", s2.top());
                s2.pop();
            }
        }
        printf("\n");
    }
    else
    {
        printf("-1\n");
    }

    return 0;
}

转载于:https://www.cnblogs.com/acboyty/p/11444137.html

题目《202305-5 闪耀巡航》是CCF CSP(中国大学生程序设计竞赛)的一个挑战题目,它通常涉及算法、数据结构和数学思维。不过,由于你提到的是Python和C++的满分题解,这说明我们需要考虑如何高效地使用这两种语言解决此问题。 闪耀巡航的问题描述一般涉及到路径优化、动态规划或者是图论中的最短路径问题。你需要帮助一个机器人在网格上找到从起点到终点的最优路线,可能会有光照限制或其他规则影响行进路径。 在Python中,可以利用Pandas处理二维数组,然后使用深度优先搜索(DFS)、广度优先搜索(BFS),或者更复杂一些,如Bellman-Ford算法来求解最短路径。记得检查边界条件和可能存在的循环引用问题。 C++方面,可以使用STL中的vector和list等容器,结合dfs函数或者Dijkstra算法(如果允许的话)。C++的迭代器和模板元编程能提高代码效率,但需要对数据结构和算法有深入理解。 以下是简化的步骤: 1. **分析问题**:明确输入格式,理解光照、障碍物等因素的影响。 2. **数据结构**:用二维数组表示地图,定义状态转移方程。 3. **选择策略**:如果是简单的遍历,用DFS;复杂一点的情况,考虑动态规划或者图搜索算法。 4. **编写代码**:递归或迭代实现算法,注意优化边界处理和空间复杂度。 5. **测试**:用样例数据验证算法是否正确,并尝试多种情况验证其鲁棒性。 至于具体的代码,这里给出一个大致框架,但因为竞赛题目细节未提供,无法给出完整的解答: ```cpp #include <iostream> using namespace std; // 用二维数组表示地图,值代表路径长度 int map[grid_size][grid_size]; // 动态规划或搜索函数 int shortestPath(int startRow, int startCol) { // 代码实现... } int main() { // 输入读取、初始化地图 // 调用shortestPath函数并打印结果 cout << shortestPath(0, 0) << endl; return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值