zoukankan      html  css  js  c++  java
  • Codeforces 1385E

    E. Directing Edges

    time limit per test3 seconds
    memory limit per test256 megabytes
    input standard input
    output standard output
    You are given a graph consisting of n vertices and m edges. It is not guaranteed that the given graph is connected. Some edges are already directed and you can’t change their direction. Other edges are undirected and you have to choose some direction for all these edges.

    You have to direct undirected edges in such a way that the resulting graph is directed and acyclic (i.e. the graph with all edges directed and having no directed cycles). Note that you have to direct all undirected edges.

    You have to answer t independent test cases.

    Input

    The first line of the input contains one integer t (1≤t≤2⋅104) — the number of test cases. Then t test cases follow.

    The first line of the test case contains two integers n and m (2≤n≤2⋅105, 1≤m≤min(2⋅105,n(n−1)2)) — the number of vertices and the number of edges in the graph, respectively.

    The next m lines describe edges of the graph. The i-th edge is described with three integers ti, xi and yi (ti∈[0;1], 1≤xi,yi≤n) — the type of the edge (ti=0 if the edge is undirected and ti=1 if the edge is directed) and vertices this edge connects (the undirected edge connects vertices xi and yi and directed edge is going from the vertex xi to the vertex yi). It is guaranteed that the graph do not contain self-loops (i.e. edges from the vertex to itself) and multiple edges (i.e. for each pair (xi,yi) there are no other pairs (xi,yi) or (yi,xi)).

    It is guaranteed that both sum n and sum m do not exceed 2⋅105 (∑n≤2⋅105; ∑m≤2⋅105).

    Output

    For each test case print the answer — “NO” if it is impossible to direct undirected edges in such a way that the resulting graph is directed and acyclic, otherwise print “YES” on the first line and m lines describing edges of the resulted directed acyclic graph (in any order). Note that you cannot change the direction of the already directed edges. If there are several answers, you can print any.

    Example
    input
    4
    3 1
    0 1 3
    5 5
    0 2 1
    1 1 5
    1 5 4
    0 5 2
    1 3 5
    4 5
    1 1 2
    0 4 3
    1 3 1
    0 2 3
    1 2 4
    4 5
    1 4 1
    1 1 3
    0 1 2
    1 2 4
    1 3 2
    output
    YES
    3 1
    YES
    2 1
    1 5
    5 4
    2 5
    3 5
    YES
    1 2
    3 4
    3 1
    3 2
    2 4
    NO
    Note
    Explanation of the second test case of the example:
    在这里插入图片描述

    Explanation of the third test case of the example:
    在这里插入图片描述

    题目大意:

    给出 t 组测试用例,对于每组样例,输入n表示这个图共有n个节点,输入m表示有m条边,接下来是m行输入,先输入0 或 1 表示有向无向,然后输入两个节点a,b,如果是1 则说明a -> b有一条有向边,判断能否通过对无向边的定向来使得图中没有自环,如果可以则输出“YES”,并以任意顺序输出m条有向边,如果发现自环则输出“NO”。

    解题思路:

    这道题的思路是如果遇到有向边存入有向边vector v,然后无论是否有方向都存入存边的向量edge,首先对有向边向量v进行dfs遍历求拓扑序,注意此时求的拓扑序是倒着的,需要reverse
    然后给每个顶点打上拓扑序的编号,之后判环。判环时,如果当前顶点的拓扑序大于当前顶点发出的边的拓扑序,则说明有环,输出NO并continue。
    如果没有环,则根据拓扑序依次输出边即可。输出是,如果y节点的拓扑序 > y节点的拓扑序,就让 y 在前,如果x的拓扑序小于y的拓扑序就让x在前,遍历完整张图即可。

    AC代码:

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <map>
    #include <set>
    using namespace std;
    vector<vector<int > > v;
    vector<int > vis;
    vector<int > tp;
    struct node {int x, y; };
    void dfs(int p)
    {
        vis[p] = 1;
        for (auto i : v[p])
        {
            if (!vis[i])
              dfs(i);
        }
        tp.push_back(p);//注意只能写在这里
    }
    int main()
    {
        int t;
        cin >> t;
        while (t--)
        {
            int n, e;
            cin >> n >> e;
            vector<node > edge;
            v = vector<vector<int> >(n);
            while (e--)
            {
                int f, a, b;
                cin >> f >> a >> b;
                a--, b--;//这里我从0开始遍历,所以都 -- ,输出的时候再加回来就行
                if (f == 1)
                    v[a].push_back(b);
                edge.push_back({a, b});
            }
            tp.clear();
            vis = vector<int >(n);
            for (int i = 0; i < n; i ++)
              if (!vis[i])
                dfs(i);
            reverse(tp.begin(), tp.end());//一开始排好的是逆序,需要反转
            vector<int > pos(n);
            for (int i = 0; i < n; i ++)
                pos[tp[i]] = i;
            bool ok = false;
            for (int i = 0; i < n; i ++)
            {
                for (auto j : v[i])
                  if (pos[i] > pos[j])
                  {
                      ok = true;
                      break;
                  }
            }
            if (ok)
            {
                cout << "NO" << endl;
                continue;
            }
            cout << "YES" << endl;
            for (auto [x, y] : edge)
            {
                if (pos[x] > pos[y])//根据拓扑关系选择先后顺序
                  cout << y + 1 << " " << x + 1 << endl;
                else
                  cout << x + 1 << " " << y + 1 << endl;
            }
        }
        return 0;
    }
    
  • 相关阅读:
    记一个SharePoint Workflow一睡永不醒来的问题
    .NET Tracing简介
    !aspxpages(即!dumphttpcontext)命令输出的解释
    MOSS定时爬网无法启动的问题
    Persistent cookies和Session cookies的定义与区别
    跨SharePoint服务器场的Content Deployment的一个知识点
    如何明确指定命令所在的debugger extension?
    理解SharePoint中的备用访问映射(Alternate Access Mapping)
    biztalk中ACK、NACK详测示例【转】
    深入biztalk消息以及消息订阅发布路由机制(一)-消息概述【转】
  • 原文地址:https://www.cnblogs.com/Hayasaka/p/14294197.html
Copyright © 2011-2022 走看看