UVALive 6467 Strahler Order(拓扑排序)

题意:

给你n个点m条边。入度为0的点标为1,如果一个点只有一个点指向,那么它标为那个点的标数。如果一个点有两个或以上相同标号的点指向。那么给它标为i+1,如果有更大的话就标为更大的。求最大的标号。

解析:

这题可以借鉴宽度优先搜索拓扑排序的思想,但是这边有一个技巧,用vis[]数组来表示当前节点是否有两个入度,如果有当前节点上有两个入度的话,就将vis[]标记为true。
每次bfs时,就将当前点的 order[u] += vis[u];

AC代码

#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
const int N = 1e3 + 10;
int n, m, indeg[N], order[N];
bool vis[N];
vector<int> g[N];
void init() {
    memset(vis, 0, sizeof(vis));
    memset(indeg, 0, sizeof(indeg));
    memset(order, 0, sizeof(order));
    for(int i = 0; i < N; i++) {
        g[i].clear();
    }
}

void add(int from, int to) {
    g[from].push_back(to);
}

int bfs() {
    queue<int> que;
    for(int i = 1; i <= n; i++) {
        if(indeg[i] == 0) {
            order[i] = 1;
            que.push(i);
        }
    }
    while(!que.empty()) {
        int u = que.front();
        que.pop();

        order[u] += vis[u];
        for(int i = 0; i < g[u].size(); i++) {
            int v = g[u][i];
            indeg[v]--;
            if(order[v] < order[u]) {
                order[v] = order[u];
                vis[v] = false;
            }else if(order[v] == order[u]) {
                vis[v] = true;
            }
            if(indeg[v] == 0)
                que.push(v);
        }
    }
    return order[n];
}

int main() {
    int T, cas;
    scanf("%d", &T);
    while(T--) {
        init();
        scanf("%d%d%d", &cas, &n, &m);
        int u, v;
        while(m--) {
            scanf("%d%d", &u, &v);
            add(u, v);
            indeg[v]++;
        }
        printf("%d %d\n", cas, bfs());
    }
    return 0;
}

你可能感兴趣的:(UVALive 6467 Strahler Order(拓扑排序))