拓扑排序简单题

来源:互联网 发布:oracle数据库面试题 编辑:程序博客网 时间:2024/05/21 09:44

确定比赛名次

题目传送: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 0x7fffffffusing 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 0x7fffffffusing 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 0x7fffffffusing 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 0x7fffffffusing 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;}



0 0
原创粉丝点击