代码源:842、排队

100 阅读2分钟

本文已参与[新人创作礼]活动,一起开启掘金创作之路 logo.png

题目描述

这是4月26日代码源div2的每日一题。

排队 - 题目 - Daimayuan Online Judge

请判断有没有一种方法可以将编号从 1 到 N 的 N 个人排成一排,并且满足给定的 M 个要求。

对于每个要求会给出两个整数 Ai 和 Bi,表示编号 Ai 和 Bi 的人是相邻的。

保证每个要求都不同,比如已经给出了 1,5,就不会再给出 1,5 或 5,1。

输入格式

第一行两个整数 N 和 M,表示 N 个人和 M 个要求。

输出格式

如果有一种能把这些人拍成一排并满足所有条件的方法,就输出 Yes,否则,输出 No。

样例输入1

4 2
1 3
2 3

样例输出1

Yes

样例输入2

4 3
1 4
2 4
3 4

样例输出2

No

样例输入3

3 3
1 2
1 3
2 3

样例输出3

No

数据规模

对于全部数据保证 2≤N≤10^5,0≤M≤10^5,1≤Ai<Bi≤N。

问题解析

对于这里的排队要求,一共有三种可能违法的情况:

1是整体是一个圈,此时每个点都至少被两个边连着。

2是有形成圈的情况,此时至少有一个点被三条边连着。

3是可能分成两个不相接的两部分(题目并没有说每个点都有要求),一个是正常的队列,一个是环。

我们先根据题目要求把所有边都连上,然后看形成的图的形状。如果有一个点被三条边连着,满足第二个条件,输出no;如果没有点是只被一条边连着,满足第一个条件,输出no。

第三个条件就比较麻烦了,我们可以先找到所有只被一条边连着的点,然后以这些点为起点遍历图,如果最后有点在提问中出现过,但没有在这次遍历中被遍历到,说明那些点自成一个环了(由于不和我们的边连着,所以遍历不到),输出no。

其余情况都输出yes。

AC代码

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>

#define endl '\n';
typedef long long ll;
typedef pair<ll, ll>PII;
const int N = 100500;

int main()
{
    int n, m;
    cin >> n >> m;
    bool flag = true;
    unordered_map<int, vector<int>>mymap;
    unordered_map<int, int>cnt;
    while (m--)
    {
        int a, b;
        cin >> a >> b;
        cnt[a] = 1;
        cnt[b] = 1;
        if (mymap[a].size() == 2)
        {
            cout << "No";
            return 0;
        }
        mymap[a].push_back(b);
        if (mymap[b].size() == 2)
        {
            cout << "No";
            return 0;
        }
        mymap[b].push_back(a);
    }
    vector<int>st;
    for (auto i : mymap)
    {
        if (i.second.size() > 2)
        {
            cout << "NO";
            return 0;
        }
        if (i.second.size() == 1)
        {
            st.push_back(i.first);
        }
    }
    int len = st.size();
    if (len == 0&&mymap.size()!=0)
    {
        cout << "No";
        return 0;
    }
    for (int i = 0; i < len; i++)
    {
        cnt[st[i]] = 0;
        int x = st[i], y = mymap[st[i]][0];
        cnt[y] = 0;
        while (1)
        {
            if (mymap[y].size() != 1)break;
            else if (mymap[y][0] != x)
            {
                cnt[mymap[y][0]] = 0;
                x = y;
                y = mymap[y][0];
            }
            else
            {
                cnt[mymap[y][1]] = 0;
                x = y;
                y = mymap[y][1];
            }
        }
    }
    for (auto i : cnt)
    {
        if (i.second == 1)
        {
            cout << "No";
            return 0;
        }
    }

    cout << "Yes";
    return 0;
}