拓扑排序简单题

确定比赛名次

题目传送:HDU – 1285 – 确定比赛名次

思路:拓扑排序

AC代码①(遍历找最小字典序):

#include <map>
#include <set>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <cstdio>
#include <cctype>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define INF 0x7fffffff
using namespace std;

int n, m;

int mp[505][505];
int deg[505];

void topo_sort() {
    for(int i = 1; i <= n; i ++) {
        for(int j = 1; j <= n; j ++) {
            if(deg[j] == 0) {
                deg[j] --;
                if(i != n) cout << j << " ";
                else cout << j << endl;
                for(int k = 1; k <= n; k ++) {
                    if(mp[j][k] == 1) {
                        deg[k] --;
                    }
                }
                break;
            }
        }
    }
}

int main() {
    while(scanf("%d %d", &n, &m) != EOF) {
        memset(mp, 0, sizeof(mp));
        memset(deg, 0, sizeof(deg));

        int u, v;
        for(int i = 0; i < m; i ++) {
            scanf("%d %d", &u, &v);
            if(!mp[u][v]) {//注意这里一个队可能赢一个队多场 
                mp[u][v] = 1;
                deg[v] ++;
            }
        }

        topo_sort();
    }
    return 0;
}

AC代码②(优先队列找最小字典序):

#include <map>
#include <set>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <cstdio>
#include <cctype>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define INF 0x7fffffff
using namespace std;

int n, m;

int deg[505];
int mp[505][505];

int topo[505];
int cnt;

void bfs() {
    priority_queue<int, vector<int>, greater<int> > q;//最小堆,因为默认为最大堆,可以通过greater来设置为最小堆 
    for(int i = 1; i <= n; i ++) {
        if(deg[i] == 0) {
            q.push(i);
        }
    }

    while(!q.empty()) {
        int t = q.top();
        q.pop();
        topo[cnt ++] = t;

        for(int i = 1; i <= n; i ++) {
            if(mp[t][i]) {
                deg[i] --;
                if(deg[i] == 0) q.push(i);
                mp[t][i] = 0;//删边 
            }
        }
    }

}

int main() {
    while(scanf("%d %d", &n, &m) != EOF) {
        memset(deg, 0, sizeof(deg));

        int u, v;
        for(int i = 0; i < m; i ++) {
            scanf("%d %d", &u, &v);
            if(!mp[u][v]) {//注意这里一个队可能赢一个队多场 
                mp[u][v] = 1;
                deg[v] ++;
            }
        }

        cnt = 0;
        bfs();

        for(int i = 0; i < cnt - 1; i ++) {
            printf("%d ", topo[i]);
        }
        printf("%d\n", topo[cnt - 1]);
    }
    return 0; 
}

产生冠军

题目传送:HDU – 2094 – 产生冠军

思路:因为只要确定是否产生冠军,根据题意可以得知当且仅当入度为0的只有一个时可以产生冠军,可以用map来映射存储的人的名字

AC代码:

#include <map>
#include <set>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <cstdio>
#include <cctype>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define INF 0x7fffffff
using namespace std;

map<string, int> mp;
int deg[1005];
int cnt;
int n;

int main() {
    while(scanf("%d", &n) != EOF) {
        if(n == 0) break;
        memset(deg, 0, sizeof(deg));
        cnt = 1;
        mp.clear();

        string s1, s2;
        for(int i = 0; i < n; i ++) {
            cin >> s1 >> s2;
// cout << s1 << " " << s2 << endl;
            if(mp.find(s1) == mp.end()) {
                mp[s1] = cnt ++;
            }
            if(mp.find(s2) == mp.end()) {
                mp[s2] = cnt ++;
            }
            int t1 = mp[s1];
            int t2 = mp[s2];
            deg[mp[s2]] ++;
        }

        int sum = 0;
        for(int i = 1; i < cnt; i ++) {
            if(deg[i] == 0) {
                sum ++;
            }
        }

        if(sum == 1) {
            printf("Yes\n");
        }
        else printf("No\n");
    }
    return 0;
}

Reward

题目传送:HDU – 2647 – Reward

思路:拓扑排序,倒着往前推,即把u->v的边在建图的时候看成v->u。

AC代码:

#include <map>
#include <set>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <cstdio>
#include <cctype>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define INF 0x7fffffff
using namespace std;

const int maxn = 10005;
int n, m;
int sum, ans;

struct node {
    int x, p;
    node() {}
    node(int _x, int _p) : x(_x), p(_p) {}
}; 

vector<int> mp[maxn];
int deg[maxn];

void topo() {
    queue<node> que;
    for(int i = 1; i <=n; i ++) {
        if(deg[i] == 0) {
            que.push(node(i, 888));
            sum --;
            ans += 888;
        }
    }

    while(!que.empty()) {
        node t = que.front();
        que.pop();

        int d = mp[t.x].size();
        for(int i = 0; i < d; i ++) {
            deg[mp[t.x][i]] --;
            if(deg[mp[t.x][i]] == 0) {
                sum --;
                ans += t.p + 1;
                que.push(node(mp[t.x][i], t.p + 1));
            }
        }
    }

}

int main() {
    while(scanf("%d %d", &n, &m) != EOF) {
        memset(deg, 0, sizeof(deg));
        for(int i = 1; i <= n; i ++) {//居然忘记初始化WA了,╮(╯▽╰)╭ 
            mp[i].clear();
        }

        int u, v;
        for(int i = 0; i < m; i ++) {
            scanf("%d %d", &u, &v);
            mp[v].push_back(u);
            deg[u] ++;
        }

        sum = n;
        ans = 0;
        topo();

        if(sum <= 0) {
            printf("%d\n", ans);
        }
        else printf("-1\n");
    }
    return 0;
}

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