简单拓扑排序的学习笔记

简单拓扑排序的学习。

拓扑排序是给有向无环图的每一个节点分级。每个节点指向的节点的等级值一定大于该节点的等级值。

bfs实现。复杂度 \(O(e+v)\)

void topo_sort()
{
    queue<int> q;
    for (int i = 1; i <= n; i++)
        if (rd[i] == 0)
        {
            q.push(i);
            ans[i] = 1;
        }
    while (!q.empty())
    {
        int now = q.front();
        q.pop();
        for (int i = 0; i < e[now].size(); i++)
        {
            rd[e[now][i]]--;
            if (rd[e[now][i]] == 0)
                q.push(e[now][i]);
            ans[e[now][i]] = max(ans[e[now][i]], ans[now] + 1);
        }
    }
}

洛谷P1347 排序

传送门

题意,给定若干个偏序,求全序。同时判断是否有矛盾。

有矛盾就是出现环了,也就是有节点无法入队。

没法排序就是有两个节点等级值相同。

\(n = 26\) 暴力出奇迹就完事了,加一条边拓扑排序一次。

甚至可以用邻接矩阵233。

这代码写的挺破的,当时初学。

#include<bits/stdc++.h>

using namespace std;

int a[100][100], f[100], rd[100], ans[100];
int n, m;

bool topo_sort(int &tot)
{
    tot = 0;
    int cnt = 0;
    queue<int> q;
    memset(f, 0, sizeof(f));
    memset(rd, 0, sizeof(rd));
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            if (a[i][j])
                rd[j]++;
    for (int i = 0; i < n; i++)
        if (rd[i] == 0)
        {
            q.push(i);
            f[i] = 1;
            ans[cnt++] = i;
            tot++;
        }
    while (!q.empty())
    {
        int now = q.front();
        q.pop();
        for (int i = 0; i < n; i++)
            if (a[now][i])
            {
                rd[i]--;
                if (rd[i] == 0)
                {
                    q.push(i);
                    tot++;
                    ans[cnt++] = i;
                }
                f[i] = max(f[now] + 1, f[i]);
            }
    }
    return tot == n;
}

int main()
{
    ios::sync_with_stdio(false);
    cin >> n >> m;
    char x, y, ch;
    int tot = 0, type = 0;
    for (int i = 0; i < m; i++)
    {
        cin >> x >> ch >> y;
        a[x - 'A'][y - 'A'] = 1;
        if (topo_sort(tot))
        {
            bool ok = true;
            for (int j = 0; j < n; j++)
                for (int k = 0; k < n; k++)
                    if (j != k && f[k] == f[j])
                    {
                        ok = false;
                        break;
                    }
            if (ok)
            {
                type = i + 1;
                break;
            }
        }
        else
        {
            cout << "Inconsistency found after " << i + 1 << " relations." << endl;
            return 0;
        }
    }
    if (type == 0)
    {
        cout << "Sorted sequence cannot be determined." << endl;
        return 0;
    }
    else
    {
        cout << "Sorted sequence determined after " << type << " relations: ";
        for (int i = 0; i < n; i++)
            cout << char(ans[i] + 'A');
        cout << "." << endl;
        return 0;
    }
}

洛谷P1137 旅行计划

传送门

有一个DAG,一个起点,求走到每个点最多能经过几个点。

简单dp的思想,其实每一个点的答案就是它的等级值。

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e5 + 10;
vector<int> e[maxn];
int ans[maxn];
int rd[maxn];
int n, m, x, y;

void topo_sort()
{
    queue<int> q;
    for (int i = 1; i <= n; i++)
        if (rd[i] == 0)
        {
            q.push(i);
            ans[i] = 1;
        }
    while (!q.empty())
    {
        int now = q.front();
        q.pop();
        for (int i = 0; i < e[now].size(); i++)
        {
            rd[e[now][i]]--;
            if (rd[e[now][i]] == 0)
                q.push(e[now][i]);
            ans[e[now][i]] = max(ans[e[now][i]], ans[now] + 1);
        }
    }
}

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 0; i < m; i++)
    {
        scanf("%d%d", &x, &y);
        e[x].push_back(y);
        rd[y]++;
    }
    topo_sort();
    for (int i = 1; i <= n; i++)
        printf("%d\n", ans[i]);
    return 0;
}

NOIP2003提高组 神经网络

传送门

较复杂状态转移。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 110;
struct node
{
    int v, nxt;
};
vector<node> e[maxn];
int n, p, x, y, w, u[maxn], rd[maxn], cd[maxn], c[maxn];
void topo_sort()
{
    queue<int> q;
    for (int i = 1; i <= n; i++)
        if (c[i] > 0)
            q.push(i);
        else
            c[i] -= u[i]; // 提前处理一下
    while (!q.empty())
    {
        int now = q.front();
        q.pop();
        if (c[now] <= 0)
            continue;
        for (int i = 0; i < e[now].size(); i++)
        {
            c[e[now][i].nxt] += e[now][i].v * c[now]; // 状态转移
            rd[e[now][i].nxt]--;
            if (rd[e[now][i].nxt] == 0)
                q.push(e[now][i].nxt);
        }
    }
}
int main()
{
    scanf("%d%d", &n, &p);
    for (int i = 1; i <= n; i++)
        scanf("%d%d", &c[i], &u[i]);
    for (int i = 0; i < p; i++)
    {
        scanf("%d%d%d", &x, &y, &w);
        e[x].push_back({ w, y });
        rd[y]++;
        cd[x]++;
    }
    topo_sort();
    bool flag = 1;
    for (int i = 1; i <= n; i++)
        if (cd[i] == 0 && c[i] > 0)
            printf("%d %d\n", i, c[i]);
    for (int i = 1; i <= n; i++)
        if (cd[i] == 0 && c[i] != 0)
            flag = 0;
    if (flag)
        puts("NULL");
    return 0;
}

NOIP2013普及组 车站分级

传送门

对于某一辆车,停的站一定比没停的等级高,如此建图。

答案就是最大的等级值。

一堆诡异的细节处理,蛋疼。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1100;
int n, m, a[maxn][maxn], s[maxn];
vector<int> stations[maxn];
int rd[maxn], e[maxn][maxn];
int ans[maxn];
void topo_sort()
{
    queue<int> q;
    for (int i = 1; i <= n; i++)
        if (rd[i] == 0)
        {
            q.push(i);
            ans[i] = 1;
        }
    while (!q.empty())
    {
        int now = q.front();
        q.pop();
        for (int i = 1; i <= n; i++)
        {
            if (e[now][i])
            {
                rd[i]--;
                if (rd[i] == 0)
                {
                    q.push(i);
                    ans[i] = max(ans[i], ans[now] + 1);
                }
            }
        }
    }
}
int main()
{
    scanf("%d%d", &n, &m);
    int x;
    for (int i = 1; i <= m; i++)
    {
        scanf("%d", &s[i]);
        for (int j = 0; j < s[i]; j++)
        {
            scanf("%d", &x);
            a[i][x] = 1;
            stations[i].push_back(x);
        }
        for (int j = stations[i][0]; j <= stations[i][s[i] - 1]; j++)
        {
            if (a[i][j] == 0)
                for (int k = stations[i][0]; k <= stations[i][s[i] - 1]; k++)
                    if (a[i][k] == 1)
                        e[j][k] = 1;
        }
    }
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            if (e[i][j])
                rd[j]++;
    topo_sort();
    int qwq = 0;
    for (int i = 1; i <= n; i++)
        qwq = max(qwq, ans[i]);
    printf("%d\n", qwq);
    return 0;
}
posted @ 2021-03-23 22:02  _slb  阅读(32)  评论(0编辑  收藏  举报