1. 程式人生 > >P2017 [USACO09DEC]暈牛Dizzy Cows

P2017 [USACO09DEC]暈牛Dizzy Cows

void int front degree 定向 ret ans top 可能

圖論日常不會系列。。。

題意:給定有向邊和無向邊,然後給每一條無向邊定向,使得到的圖無環。

我本來想縮一下點的,但是越想越暈。

然後就翻了題解,恍然大悟。。。

其實只需要給只有有向邊的圖跑一次toposort。然後把無向邊的定向看做是在添加有向邊。

顯然不要違反拓撲序來添加有向邊,這個圖就不可能有環!

所以隨便搞一搞就好了。。。

代碼:

#include<cstdio>

#include<queue>
const int maxn = 100005;
struct Edges
{
    int next, to;
} e[maxn * 3];
int head[maxn], tot;
int indegree[maxn];
int topo[maxn], ttot;
int where[maxn];
struct Query
{
    int u, v;
} Q[maxn];
int n, m1, m2;
int read()
{
    int ans = 0, s = 1;
    char ch = getchar();
    while(ch > ‘9‘ || ch < ‘0‘){ if(ch == ‘-‘) s = -1; ch = getchar(); }
    while(ch >= ‘0‘ && ch <= ‘9‘) ans = (ans << 3) + (ans << 1) + ch - ‘0‘, ch = getchar();
    return s * ans;
}
void link(int u, int v)
{
    e[++tot] = (Edges){head[u], v};
    head[u] = tot;
}
void toposort()
{
    std::queue<int> q;
    for(int i = 1; i <= n; i++) if(indegree[i] == 0) q.push(i);
    while(!q.empty())
    {
        int u = q.front(); q.pop();
        topo[++ttot] = u;
        for(int i = head[u]; i; i = e[i].next)
        {
            int v = e[i].to;
            indegree[v]--;
            if(indegree[v] == 0)
            {
                q.push(v);
            }
        }
    }
}
int main()
{
    n = read(), m1 = read(), m2 = read();
    while(m1--)
    {
        int u = read(), v = read();
        link(u, v);
        indegree[v]++;
    }
    for(int i = 1; i <= m2; i++)
    {
        Q[i].u = read(), Q[i].v = read();
        
    }
    toposort();
    for(int i = 1; i <= ttot; i++) where[topo[i]] = i;
    for(int i = 1; i <= m2; i++)
    {
        int temp1 = where[Q[i].u], temp2 = where[Q[i].v];
        if(temp1 < temp2) printf("%d %d\n", Q[i].u, Q[i].v);
        else printf("%d %d\n", Q[i].v, Q[i].u);
    }
    return 0;
}

P2017 [USACO09DEC]暈牛Dizzy Cows