hello大家好,我是拓扑排序

发几个以前写的拓扑排序,回顾一下。

拓扑排序,一般不会单独考,主要要求还是掌握好这个概念,有个感性的认识,以及能快速的写出求拓扑排序的程序,进而继续接下来对图的处理,或是比如dp之类的算法,又或者是判断有无环之类。求拓扑序主要就是运用队列,push入度为0的点,删掉它们出去的边,重复这个操作。像要是求字典序最小,就可以用优先队列。

TOJ 3993 求字典序最小的拓扑排序

 1 #include<cstdio>
 2 #include<queue>
 3 #include<cstring>
 4 using namespace std;
 5 
 6 int ans[110], in[110];
 7 bool e[110][110];
 8 int n, m;
 9 int main()
10 {
11     int T, x, y;
12     scanf("%d", &T);
13     while(T--)
14     {
15         memset(e, 0, sizeof(e));
16         memset(in, 0, sizeof(in));
17         scanf("%d %d", &n, &m);
18         for (int i = 0; i < m; i++){
19             scanf("%d %d", &x, &y);
20             if (!e[x][y]){
21                 e[x][y] = 1;
22                 in[y]++;
23             }
24         }
25         priority_queue<int, vector<int>, greater<int> > q;
26         for (int i = 1; i <= n; i++)
27             if (!in[i]) q.push(i);
28         int cnt = 0;
29         while(!q.empty()){
30             int u = q.top();
31             q.pop();
32             ans[++cnt] = u;
33             for (int i = 1; i <= n; i++)
34                 if (e[u][i]){
35                     in[i]--;
36                     if (!in[i]) q.push(i);
37                 }
38         }
39         if (cnt == n){
40             for (int i = 1; i <= n; i++)
41                 printf("%d ", ans[i]);
42             printf("\n");
43         }
44         else printf("Low IQ\n");
45     }
46     return 0;
47 }
View Code

 

POJ 3687 反向建图求拓扑排序

 1 #include<cstring>
 2 #include<cstdio>
 3 #include<queue>
 4 using namespace std;
 5 
 6 int ans[210], in[210];
 7 bool e[210][210];
 8 int main()
 9 {
10     int T, n, m, x, y;
11     scanf("%d", &T);
12     while(T--)
13     {
14         memset(e, false, sizeof(e));
15         memset(in, 0, sizeof(in));
16         scanf("%d %d", &n, &m);
17         for (int i = 0; i < m; i++){
18             scanf("%d %d", &x, &y);
19             if (!e[y][x]){
20                 e[y][x] = true;
21                 in[x] ++;
22             }
23         }
24         priority_queue<int> q;
25         for (int i = 1; i <= n; i++)
26             if (!in[i]) q.push(i);
27         int cnt = n;
28         while(!q.empty()){
29             int u = q.top(); q.pop();
30             ans[u] = cnt --;
31             for (int i = 1; i <= n; i++)
32                 if (e[u][i]){
33                     in[i] --;
34                     if (!in[i]) q.push(i);
35                 }
36         }
37         if (cnt == 0){
38             for (int i = 1; i < n; i++)
39                 printf("%d ", ans[i]);
40             printf("%d\n", ans[n]);
41         }
42         else printf("-1\n");
43     }
44     return 0;
45 }
View Code

 

POJ 1270 按字典序输出所有拓扑排序,这个代码写得比较dirty

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<queue>
 4 #include<algorithm>
 5 #include<string>
 6 #include<iostream>
 7 using namespace std;
 8 
 9 char s1[1000], s2[1000];
10 string ans[400];
11 int n, cnt;
12 bool vis[50], e[50][50];
13 int in[50], a[50];
14 void dfs(int dep, string ss)
15 {
16     if (dep == n){
17         ans[cnt++] = ss;
18         return;
19     }
20     for (int i = 0; i < n; i++)
21         if (!in[a[i]] && !vis[a[i]]){
22             vis[a[i]] = true;
23             char tmp = a[i] + 'a' - 1;
24             ss.append(1, tmp);
25             for (int j = 0; j < n; j++)
26                 if (e[a[i]][a[j]]) in[a[j]] --;
27             
28             dfs(dep+1, ss);
29 
30             vis[a[i]] = false;
31             ss.erase(ss.length()-1, 1);
32             for (int j = 0; j < n; j++)
33                 if (e[a[i]][a[j]]) in[a[j]] ++;
34         }
35     return;
36 }
37 bool cmp(string a, string b){
38     return a < b;
39 }
40 int main()
41 {
42     bool flag = true;
43     while(cin.getline(s1, 1000))
44     {
45         if (flag) flag = false;
46         else printf("\n");
47         cin.getline(s2, 1000);
48         n = 0;
49         for (int i = 0; i < strlen(s1); i++){
50             if (s1[i] != ' '){
51                 a[n++] = s1[i] - 'a' + 1;
52             }
53         }
54 //        for (int i = 0; i < n; i++)
55 //            printf("%d\n", a[i]);
56         memset(e, 0, sizeof(e));
57         memset(in, 0, sizeof(in));
58         memset(vis, false, sizeof(vis));
59         int p1 = 0, p2 = 0;
60         for (int i = 0; i < strlen(s2); i++){
61             if (s2[i] != ' '){
62                 if (p1 == 0){
63                     p1 = s2[i] - 'a' + 1;
64                 }
65                 else{
66                     p2 = s2[i] - 'a' + 1;
67                     e[p1][p2] = true;    
68                     in[p2] ++;
69                     p1 = p2 = 0;
70                 }
71             }
72         }
73         string ss = "";
74         cnt = 0;
75         dfs(0, ss);
76         sort(ans, ans+cnt, cmp);
77         for (int i = 0; i < cnt; i++)
78             cout << ans[i] << endl;
79     }
80     return 0;
81 }
View Code

 

HDU 1285 求字典序最小拓扑序

 1 #include<cstring>
 2 #include<cstdio>
 3 #include<queue>
 4 using namespace std;
 5 
 6 int en[510], in[510];
 7 int n, m, x, y, esize;
 8 struct edge{
 9     int n, v;
10 } e[30000];
11 void insert(int u, int v)
12 {
13     esize ++;
14     e[esize].v = v;
15     e[esize].n = en[u];
16     en[u] = esize;
17 }
18 int main()
19 {
20     while(scanf("%d %d", &n, &m) != EOF)
21     {
22         memset(en, -1, sizeof(en));
23         memset(in, 0, sizeof(in));
24         esize = -1;
25         for(int i = 0; i < m; i++){
26             scanf("%d %d", &x, &y);
27             insert(x, y);
28             in[y]++;
29         }
30         priority_queue<int, vector<int>, greater<int> > q;
31         for (int i = 1; i <= n; i++){
32             if (!in[i]) q.push(i);
33         }
34         bool flag = true;
35         while(!q.empty()){
36             int t = q.top(); q.pop();
37             if (flag){
38                 flag = false;
39                 printf("%d", t);
40             }
41             else printf(" %d", t);
42             for (int tt = en[t]; tt != -1; tt = e[tt].n){
43                 int v = e[tt].v;
44                 in[v]--;
45                 if (!in[v]) q.push(v);
46             }
47         }
48         printf("\n");
49     }
50     return 0;
51 }
View Code

 

HDU 3231 在三个坐标轴方向上做拓扑排序,对这题还挺有印象,当时wa了好几次卡了很久,记得这题还是某个区预赛的题。不知道真到比赛,会是什么样。我能很快的做出来吗?

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<queue>
 4 using namespace std;
 5 
 6 struct edge{
 7     int n, v;
 8 } e[3][603000];
 9 int ans[3000][3], en[3][3000], in[3][3000];
10 int n, r, esize[3];
11 void insert(int t, int u, int v)
12 {
13     e[t][esize[t]].v = v;
14     e[t][esize[t]].n = en[t][u];
15     en[t][u] = esize[t];
16     esize[t] ++;
17     in[t][v]++;
18 }
19 int main()
20 {
21     int x, y, ca = 0;
22     char ch[10];
23     while(scanf("%d %d", &n, &r) && (n + r))
24     {
25         ca ++;
26         memset(in, 0, sizeof(in));
27         memset(en, -1, sizeof(en));
28         memset(esize, 0, sizeof(esize));
29         for (int i = 1; i <= n; i++){
30             insert(0, i, i+n);
31             insert(1, i, i+n);
32             insert(2, i, i+n);
33         }
34         for (int i = 0; i < r; i++){
35             //getchar();
36             scanf("%s %d %d", ch, &x, &y);
37             if (ch[0] == 'I'){
38                 insert(0, x, y+n);
39                 insert(1, x, y+n);
40                 insert(2, x, y+n);
41                 insert(0, y, x+n);
42                 insert(1, y, x+n);
43                 insert(2, y, x+n);
44             }
45             else if (ch[0] == 'X'){
46                 insert(0, x+n, y);
47             }
48             else if (ch[0] == 'Y'){
49                 insert(1, x+n, y);
50             }
51             else if (ch[0] == 'Z')
52                 insert(2, x+n, y);
53         }
54         bool findans = true;
55         for (int t = 0; t < 3; t++){
56             queue<int> q;
57             for (int i = 1; i <= n * 2; i++){
58                 if (in[t][i] == 0) {//printf("t:%d %d\n", t, i);
59                     q.push(i);
60                 }
61             }
62             int u, v, p;
63             int cnt = 0;
64             while(!q.empty()){
65                 int u = q.front(); q.pop();
66                 ans[u][t] = ++cnt;
67                 for (p = en[t][u]; p != -1; p = e[t][p].n){
68                     v = e[t][p].v;
69                     in[t][v] --;
70                     if (!in[t][v]){//printf("t:%d %d\n", t, v);
71                         q.push(v);
72                     }
73                 }
74             }
75             //printf("%d\n", cnt);
76             if (cnt != (n*2)) {findans = false; break;}
77         }
78         if (findans){
79             printf("Case %d: POSSIBLE\n", ca);
80             for (int i = 1; i <= n; i++)
81                 printf("%d %d %d %d %d %d\n", ans[i][0], ans[i][1], ans[i][2], 
82                                   ans[i+n][0], ans[i+n][1], ans[i+n][2]);
83         }
84         else
85             printf("Case %d: IMPOSSIBLE\n", ca);
86         if (ca >= 1) printf("\n");
87     }
88     return 0;
89 }
View Code
posted @ 2014-08-10 21:49  james47  阅读(163)  评论(0编辑  收藏  举报