CodeForces 915D Almost Acyclic Graph(拓扑排序)

D. Almost Acyclic Graph time limit per test:1 second memory limit per test:256 megabytes input:standard input output:standard output

You are given a directed graph consisting of n vertices and m edges (each edge is directed, so it can be traversed in only one direction). You are allowed to remove at most one edge from it.

Can you make this graph acyclic by removing at most one edge from it? A directed graph is called acyclic iff it doesn’t contain any cycle (a non-empty path that starts and ends in the same vertex).

Input

The first line contains two integers n and m (2 ≤ n ≤ 500,1 ≤ m ≤ min(n(n - 1), 100000)) — the number of vertices and the number of edges, respectively.

Then m lines follow. Each line contains two integers u and v denoting a directed edge going from vertex u to vertex v (1 ≤ u, v ≤ n,u ≠ v). Each ordered pair (u, v) is listed at most once (there is at most one directed edge fromu tov).

Output

If it is possible to make this graph acyclic by removing at most one edge, print YES. Otherwise, print NO.

Examples Input

3 4
1 2
2 3
3 2
3 1

Output

YES

Input

5 6
1 2
2 3
3 2
3 1
2 1
4 5

Output

NO

Note

In the first example you can remove edge 《CodeForces 915D Almost Acyclic Graph(拓扑排序)》, and the graph becomes acyclic.

In the second example you have to remove at least two edges (for example, 《CodeForces 915D Almost Acyclic Graph(拓扑排序)》 and 《CodeForces 915D Almost Acyclic Graph(拓扑排序)》) in order to make the graph acyclic.

        这题居然是topsort……

        大致题意就是给你一个图,然后最短删除一条边,问你是否能够把这个图变成一个DAG有向无环图。

        暴力的话枚举所有的边,然后再遍历图,复杂度为O(M*(N+M))果断超时。自己画出图来找一些环的个数以及相互之间的重边的关系,还是没有能够找到一个很好的规律。另一个方法就是,找出一个的环,然后标记环上的边,枚举这些边删掉,看是否还有环。但是这个操作起来不好处理,本身求具体的环就要用tarjan,然后还要在上面修改标记下环上的边……

        正解是,既然删掉一条边对度的改变是是一个点入度减一,另一个点的出度减一,而拓扑排序正好可以判断环而且与入度关联,因此我们考虑枚举一个点,这个点关联被删掉的边入度减一。我们把枚举的点入度减一,看看之后能否完整的做完拓扑排序,如果可以那么就有解,否则没有。那么这个正确性如何理解呢?我们可以这样想,少一条边,相当于某个点入度减一,而这个点入度减一之后能否做完拓扑排序,则对应是否还有环,这样就对应过来了。或者也可以理解为,枚举环上的点,让他入度减一,相当于破掉与其关联的一个环,再看是否有环。

        具体见代码:

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define LL long long
#define N 510

using namespace std;

int n,m,d[N],a[N];
vector<int> g[N];

bool topsort(int x)
{
    memcpy(a,d,sizeof(d));
    int num=0; a[x]--; queue<int> q;
    for(int i=1;i<=n;i++)
        if (a[i]==0) q.push(i),num++;
    while(!q.empty())
    {
        int i=q.front(); q.pop();
        for(int j=0;j<g[i].size();j++)
            if (!(--a[g[i][j]])) q.push(g[i][j]),num++;
    }
    return num==n;
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        g[u].push_back(v); d[v]++;
    }
    for(int i=1;i<=n;i++)
        if (topsort(i))
        {
            puts("YES");
            return 0;
        }
    puts("NO");
    return 0;
}

    原文作者:拓扑排序
    原文地址: https://blog.csdn.net/u013534123/article/details/79317010
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞