题目链接

题意 : 给出 N 个点(最多 1e6 )和 M 条边 (最多 N + 20 条 )要你输出一条从 1 开始回到 1 的哈密顿回路路径,不存在则输出 " There is no route, Karl! "

分析 : 

题意很简单明了

众所周知,哈密顿回路是个 NP-Hard 问题

这么多个点的哈密顿回路肯定是不能暴力去寻找的

但是关注到 M ≤ N + 20 这个特殊的条件

那就说明图中肯定有很多单向链

那么这题就很明确了,就把所有的单链缩成一个点

然后再去 DFS 暴力找

口胡起来貌似很简单,写起来是真的 _(´ཀ`」 ∠)_

写了我挺久的,主要是Debug了挺久

#include<bits/stdc++.h>
using namespace std;
;
];
];///记录链的出度和入度
int N, M, Head[maxn], cnt;
int id, st;///分配ID的计数变量、寻找哈密顿回路的起点
int IN[maxn], OUT[maxn];///每个点的入度和出度数量,方便判断一个节点是否为单链的节点
int ID[maxn], vtx[maxn];///每个节点重新分配的ID、每个ID对应的节点or链
bool isChain[maxn], vis[maxn];///判断是否是链、DFS中的判重数组
int c[maxn];///并查集数组,判断图是否弱连通
vector<int> arr;///存储最终答案

int Findset(int x)
{
    int root = x;
    while(c[root] != root)
        root = c[root];

    int idx;
    while(c[x] != root){
        idx = c[x];
        c[x] = root;
        x = idx;
    }
    return root;
}

inline void Join(int a, int b)
{
    int A = Findset(a);
    int B = Findset(b);
    if(A != B) c[A] = B;
}

inline void init()
{
    ; i<maxn; i++) c[i] = i;
    memset(ID, -, sizeof(ID));
    memset(vtx, -, sizeof(vtx));
    memset(Head, -, sizeof(Head));
    memset(isChain, false, sizeof(isChain));
    cnt = id = ;
    st = -;
}

inline void AddEdge(int From, int To)
{
    Edge[cnt].v = To;
    Edge[cnt].nxt = Head[From];
    Head[From] = cnt++;
}

inline void ColorChain(int v, int Eiv, int Eid)
{
    Chain[id][] = v;
    bool loop = false;///链有可能构成环、如果是环,则出入度是一样的,标记一下

     || OUT[Eiv] != )){
        ) { ID[Eiv] = id; ) vtx[id] = Eiv; }
        else { loop = true; break; }

        isChain[Eiv] = true;

        Eiv = Edge[Eid].v;
        Eid = Head[Eiv];
    }

    Chain[id][] = loop ? v : Eiv;

    id++;
}

inline void Color(int v)
{
     && OUT[v] == ) return;///如果是单链上的节点就跳过,因为我的染色找链
                                         ///总是去找链的入度节点才去为这个链分配ID

    Chain[id][] = v, Chain[id][] = -;///可以无视这个,没啥用
    ID[v] = id++;
    vtx[id-] = v;
    int Eid, Eiv;

    ; i=Edge[i].nxt){
        Eiv = Edge[i].v;
        Eid = i;
         && OUT[Eiv] == )///说明v是一个链的入度
            ColorChain(v, Eiv, Head[Eiv]);///为链染色
    }
}

int ans[maxn];
bool DFS(int v, int num)///寻找哈密顿回路,分是否是链的两种情况
{
    if(num == id && v == st) return true;
    if(vis[ID[v]]) return false;

    vis[ID[v]] = true;
    ans[num] = ID[v];

    if(isChain[v]){
        ], num+) )///如果是链的开头,直接递归进其出度
            return true;
    }else{
        ; i=Edge[i].nxt)///如果不是链则正常访问其所有出度
            ) )
                return true;;
    }

    vis[ID[v]] = false;
    return false;
}

inline void Print_Chain(int v, int Chain_id)
{
     && OUT[v]==){
        arr.push_back(v);
        v = Edge[Head[v]].v;
    }
}

int main(void)
{
    freopen("king.in", "r", stdin);///提交记得加这两个 freopen
    freopen("king.out", "w", stdout);
    scanf("%d %d", &N, &M);

    init();

    int From, To;
    while(M--){
        scanf("%d %d", &From, &To);
        AddEdge(From, To);
        Join(From, To);
        IN[To]++, OUT[From]++;
    }

    );
    ; i<=N; i++){
        if(Findset(i) != root){
            puts("There is no route, Karl!");
            ;
        }
    }

    ; i<=N; i++){
         && (IN[i] !=  || OUT[i] != )) st = i;
        ) continue;
        else Color(i);///给每一个点配上一个ID,如果是链,则链上顶点ID一致,
                      ///且当前节点 isChain = true 标记是链
    }

    ){
        ;
        bool flag = true;
        ){
            flag = false;
            printf("%d ", v);
            v = Edge[Head[v]].v;
        }puts(");
        ;
    }

    memset(vis, false, sizeof(vis));
    )){
        ; i<id; i++){
           int cur = vtx[ans[i]];
           if(isChain[cur]) Print_Chain(cur, ans[i]);
           else arr.push_back(cur);
        }

        bool BEGIN = false;
        ;
        int len = arr.size();

        ; i<len && Count<len; i=(i+)%len){///因为不保证总是从1开始dfs,所以要去调整一下输出
            ) BEGIN = true;
            if(BEGIN){
                printf("%d ", arr[i]);
                Count++;
            }
        }puts(");

    }else puts("There is no route, Karl!");
    ;
}
/*
10 11
10 8
5 4
9 1
4 3
7 2
2 6
6 5
8 9
1 7
10 3
3 10
*/

Codeforces Gym 100851 K King's Inspection ( 哈密顿回路 && 模拟 )的更多相关文章

  1. 【二分】NEERC15 L Landscape Improved(2015-2016 ACM-ICPC)(Codeforces GYM 100851)

    题目链接: http://codeforces.com/gym/100851 题目大意: 一个宽度为N的网格图,i上有h[i]高的方块.现在你有W个方块,问怎么放使得最终的最高点最高. 只要一个格子的 ...

  2. 【模拟】NEERC15 G Generators(2015-2016 ACM-ICPC)(Codeforces GYM 100851)

    题目链接: http://codeforces.com/gym/100851 题目大意: n个序列.每个序列有4个值x,a,b,c,之后按照x=(a*x+b)%c扩展无穷项. 求每个序列各取一个数之后 ...

  3. 【模拟】NEERC15 J Jump(2015-2016 ACM-ICPC)(Codeforces GYM 100851)

    题目链接: http://codeforces.com/gym/100851 题目大意: 系统里生成一个字符串C,一开始告诉你字符串的长度N(偶数).接着你需要在n+500次内猜出这个字符串是什么. ...

  4. 【最短路】NEERC15 F Froggy Ford(2015-2016 ACM-ICPC)(Codeforces GYM 100851)

    题目链接: http://codeforces.com/gym/100851 题目大意: 一只青蛙跳过宽为W的河,河中游N个石头,坐标xi,yi,现在往河中间添加一个石头,使得每次跳跃的最大的距离最小 ...

  5. 【模拟】NEERC15 E Easy Problemset (2015-2016 ACM-ICPC)(Codeforces GYM 100851)

    题目链接: http://codeforces.com/gym/100851 题目大意: N个人,每个人有pi个物品,每个物品价值为0~49.每次从1~n顺序选当前这个人的物品,如果这个物品的价值&g ...

  6. 【模拟】NEERC15 A Adjustment Office (2015-2016 ACM-ICPC)(Codeforces GYM 100851)

    题目链接: http://codeforces.com/gym/100851 题目大意: 一个N*N的矩阵A,Ai,j=i+j,Q次操作,每次分两种,R r取出第r行还未被取的所有数,并输出和.C c ...

  7. Codeforces Gym 100187K K. Perpetuum Mobile 构造

    K. Perpetuum Mobile Time Limit: 2 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100187/pro ...

  8. codeforces gym 100971 K Palindromization 思路

    题目链接:http://codeforces.com/gym/100971/problem/K K. Palindromization time limit per test 2.0 s memory ...

  9. CF gym 101933 K King's Colors —— 二项式反演

    题目:http://codeforces.com/gym/101933/problem/K 其实每个点的颜色只要和父亲不一样即可: 所以至多 i 种颜色就是 \( i * (i-1)^{n-1} \) ...

随机推荐

  1. JMS(Java消息服务)入门教程(一)

    什么是Java消息服务 Java消息服务指的是两个应用程序之间进行异步通信的API,它为标准消息协议和消息服务提供了一组通用接口,包括创建.发送.读取消息等,用于支持JAVA应用程序开发.在J2EE中 ...

  2. Log的相关用法

    1.最好用静态final定义Log变量 private static final Log log = LogFactory.getLog(MyTest.class); 这样做的好处有三: 可以保证线程 ...

  3. [POI2011]SMI-Garbage 题解

    题面 想必各位大佬一定想到了把现在和目标值不一致的边加入到一个新建的图上: 问题就变为了在新的图上寻找有多少个欧拉回路,并输出这些路径: 我们可以用栈来记录情况,然后对于会回答稍微处理处理就好了: # ...

  4. Android-Widget桌面小组件

    1, 掌握Widget的用:Widget的用途,能够添加到手机桌面的程序 2, Widget的特点和用法步骤: 特点:快捷,方便,个性化,可自定义功能,可及时控制更新Widget显示内容 3, 用法步 ...

  5. python_操作MySQL 初解

    单文件操作数据库 import random import threading, multiprocessing import time, datetime import pymysql import ...

  6. Nginx教程(一)-全面认知

    什么是 nginx nginx 是一款高性能的 http 服务器,反向代理服务器,电子邮件(IMAP/POP3)代理服务器: 它的特点就是高性能,占用内存少,支持高并发,运行稳定: 官方测试 可支持 ...

  7. APT高持续渗透攻击-后门篇

    APT是指高级持续性威胁, 利用先进的攻击手段对特定目标进行长期持续性网络攻击的攻击形式,APT攻击的原理相对于其他攻击形式更为高级和先进,其高级性主要体现在APT在发动攻击之前需要对攻击对象的业务流 ...

  8. uoj218_火车管理

    题意 \(n\)个位置,每个位置一个栈,三种操作,询问区间栈顶的和,区间入栈某个数,单点出栈某个数. 分析 用一个线段树来维护栈顶的和,区间(单点)更新和区间询问. 用一个主席树来维护每个位置最新一次 ...

  9. Codeforces 1220C. Substring Game in the Lesson

    传送门 首先显然的,如果 $l$ 能移动,那么 $r$ 一定可以随便移动,如果 $l$ 不动,那么 $r$ 一定不能动 那么我们现在只要考虑 $l$ 的移动即可 考虑找到位置 $k$ 之前的最左边的最 ...

  10. web端生成的带有echarts图表的html页面,嵌入在(javaFx)webview中显示错位问题

    web项目需要嵌入到手机APP的webview里面以及 windows客户端应用(JavaFx)的webview里面,这个时候就出现了问题. echarts渲染的时候根据浏览器不同的内核显示是有区别的 ...