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 }

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 }

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 }

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 }

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 }

hello大家好,我是拓扑排序,布布扣,bubuko.com

时间: 2024-10-11 02:48:53

hello大家好,我是拓扑排序的相关文章

拓扑排序 - 并查集 - Rank of Tetris

Description 自从Lele开发了Rating系统,他的Tetris事业更是如虎添翼,不久他遍把这个游戏推向了全球. 为了更好的符合那些爱好者的喜好,Lele又想了一个新点子:他将制作一个全球Tetris高手排行榜,定时更新,名堂要比福布斯富豪榜还响.关于如何排名,这个不用说都知道是根据Rating从高到低来排,如果两个人具有相同的Rating,那就按这几个人的RP从高到低来排. 终于,Lele要开始行动了,对N个人进行排名.为了方便起见,每个人都已经被编号,分别从0到N-1,并且编号越

拓扑排序 - 确定比赛名次

Description 有N个比赛队(1<=N<=500),编号依次为1,2,3,....,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得每个队的比赛成绩,只知道每场比赛的结果,即P1赢P2,用P1,P2表示,排名时P1在P2之前.现在请你编程序确定排名. Input 输入有若干组,每组中的第一行为二个数N(1<=N<=500),M:其中N表示队伍的个数,M表示接着有M行的输入数据.接下来的M行数据中,每行也有两个整数P1,P2表示

Day1:T1 模拟 T2 拓扑排序

T1:模拟 自己第一天的简直跟白痴一样啊...模拟都会打错.. 当时貌似在更新最大值的时候打逗比了... if((sum[x]==max && x<maxh) || sum[x]>max){  max=sum[x];  maxh=x; //现在(也就是9月+)再看,脑袋里只有sortsortsort,连最基本的更新最大指都忘了....智商唉.... 附上代码: #include<cstdio> #include<cstring> using namesp

HDU 4857 逃生 拓扑排序好题 第一次做CLJ出的题

逃生 Problem Description 糟糕的事情发生啦,现在大家都忙着逃命.但是逃命的通道很窄,大家只能排成一行. 现在有n个人,从1标号到n.同时有一些奇怪的约束条件,每个都形如:a必须在b之前.同时,社会是不平等的,这些人有的穷有的富.1号最富,2号第二富,以此类推.有钱人就贿赂负责人,所以他们有一些好处. 负责人现在可以安排大家排队的顺序,由于收了好处,所以他要让1号尽量靠前,如果此时还有多种情况,就再让2号尽量靠前,如果还有多种情况,就让3号尽量靠前,以此类推. 那么你就要安排大

【tarjan 拓扑排序 dp】bzoj1093: [ZJOI2007]最大半连通子图

思维难度不大,关键考代码实现能力.一些细节还是很妙的. Description 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向路径.若G'=(V',E')满足V'?V,E'是E中所有跟V'有关的边,则称G'是G的一个导出子图.若G'是G的导出子图,且G'半连通,则称G'为G的半连通子图.若G'是G所有半连通子图中包含节点数最多的,则称G'是G的最大半连通子图.给

关于拓扑排序

拓扑排序 英文名称:Topological-sort 别称:toposort or  topsort 以下进入胡扯时间 正题: 排序??? a:我有sort! b:我还会桶排! c:我我我!我还会基数排序和计数排序 哇塞!厉害! 但是你会这些东西和我拓扑排序有什么关系 a??b??c??? 拓扑排序是干什么的呢 对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线

拓扑排序讲解

在这里我们要说的拓扑排序是有前提的 我们在这里说的拓扑排序是基于有向无环图的!!!. (⊙o⊙)…我所说的有向无环图都知道是什么东西吧.. 如果不知道,我们下面先来来说说什么是有向无环图. 所谓有向无环图,顾名思义是不存在环的有向图(至于有向图是什么不知道的在前面我们有一个图论讲解上都有). 点的入度:以这个点为结束点的边数. 点的出度:以这个点为出发点的边的条数. 拓扑序就是对于一个节点的一个排列,使得(u,v)属于E,那么u一定出现在v的前面.然而拓扑排序就是一个用来求拓扑序的东西. 对于左

CSU 1804: 有向无环图(拓扑排序)

http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1804 题意:…… 思路:对于某条路径,在遍历到某个点的时候,之前遍历过的点都可以到达它,因此在这个时候对答案的贡献就是∑(a1 + a2 + a3 + ... + ai) * bv,其中a是之前遍历到的点,v是当前遍历的点. 这样想之后就很简单了.类似于前缀和,每次遍历到一个v点,就把a[u]加给a[v],然后像平时的拓扑排序做就行了. 1 #include <bits/stdc++.h>

7-9-有向图无环拓扑排序-图-第7章-《数据结构》课本源码-严蔚敏吴伟民版

课本源码部分 第7章  图 - 有向无环图拓扑排序 ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑        本源码引入的文件  链接? Status.h.SequenceStack.c.ALGraph.c