UVA10305 拓扑序

题意:给出多个任务,以及一系列任务的关系表示某个任务必须在某个任务前完成,问一个合理的任务完成顺序

拓扑序的裸题,一开始用大白书的写法,后来发现并不好用,就换了BFS又A了一遍。

原:

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 using namespace std;
 5 const int maxm=105;
 6
 7 int vis[maxm],topo[maxm],t;
 8 int head[maxm],point[maxm*maxm],nxt[maxm*maxm],size;
 9
10 void add(int a,int b){
11     point[size]=b;
12     nxt[size]=head[a];
13     head[a]=size++;
14 }
15
16 bool dfs(int s){
17     vis[s]=-1;
18     for(int i=head[s];~i;i=nxt[i]){
19         int j=point[i];
20         if(vis[j]==-1)return 0;
21         if(!vis[j]&&!dfs(j))return 0;
22     }
23     vis[s]=1;
24     topo[t--]=s;
25     return 1;
26 }
27
28 bool toposort(int n){
29     t=n;
30     memset(vis,0,sizeof(vis));
31     for(int i=1;i<=n;++i){
32         if(!vis[i]){
33             if(!dfs(i))return 0;
34         }
35     }
36     return 1;
37 }
38
39 int main(){
40     int n,m;
41     while(scanf("%d%d",&n,&m)!=EOF&&n+m){
42         memset(head,-1,sizeof(head));
43         size=0;
44         for(int i=1;i<=m;++i){
45             int a,b;
46             scanf("%d%d",&a,&b);
47             add(a,b);
48         }
49         toposort(n);
50         for(int i=1;i<=n;++i){
51             printf("%d",topo[i]);
52             if(i==n)printf("\n");
53             else printf(" ");
54         }
55     }
56     return 0;
57 }

BFS:

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<queue>
 4 using namespace std;
 5
 6 int ma[105][105],id[105],n;
 7
 8 void init(){
 9     memset(ma,0,sizeof(ma));
10     memset(id,0,sizeof(id));
11 }
12
13 void topo(){
14     queue<int>q;
15     for(int i=1;i<=n;++i)if(!id[i])q.push(i);
16     int cnt=0;
17     while(!q.empty()){
18         int u=q.front();
19         q.pop();
20         printf("%d",u);
21         if(++cnt==n)printf("\n");
22         else printf(" ");
23         for(int i=1;i<=n;++i)if(ma[u][i]){
24             id[i]--;
25             if(!id[i])q.push(i);
26         }
27     }
28 }
29
30 int main(){
31     int m;
32     while(scanf("%d%d",&n,&m)!=EOF&&n+m){
33         init();
34         while(m--){
35             int a,b;
36             scanf("%d%d",&a,&b);
37             if(!ma[a][b]){
38                 ma[a][b]=1;
39                 id[b]++;
40             }
41         }
42         topo();
43     }
44     return 0;
45 }

时间: 2024-10-15 13:19:41

UVA10305 拓扑序的相关文章

bzoj 1880 [Sdoi2009]Elaxia的路线(最短路+拓扑序)

Description 最近,Elaxia和w**的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间.Elaxia和w**每天都要奔波于宿舍和实验室之间,他们 希望在节约时间的前提下,一起走的时间尽可能的长. 现在已知的是Elaxia和w**所在的宿舍和实验室的编号以及学校的地图:地图上有N个路 口,M条路,经过每条路都需要一定的时间. 具体地说,就是要求无向图中,两对点间最短路的最长公共路径. Input 第一行:两个整数N和M(含义如题目描述).

[BZOJ 1103][POI 2007]大都市(DFS求拓扑序+树状数组)

题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1103 题目大意:给你一个树,刚开始所有树边边权均为1,不断地将其中的某些边边权改为0,其间问你某个点到根节点之间路径上的边权和. 此题和POJ的Apple Tree很相近... 首先DFS生成整棵树的拓扑序,DFS时每个结点i进入的时间l[i]和离开的时间r[i],然后对每次更改操作,维护树状数组即可. #include <iostream> #include <stdi

hdu-4857 逃生(拓扑序)

题目链接: 逃生 Time Limit: 2000/1000 MS (Java/Others)     Memory Limit: 32768/32768 K (Java/Others) Problem Description 糟糕的事情发生啦,现在大家都忙着逃命.但是逃命的通道很窄,大家只能排成一行. 现在有n个人,从1标号到n.同时有一些奇怪的约束条件,每个都形如:a必须在b之前.同时,社会是不平等的,这些人有的穷有的富.1号最富,2号第二富,以此类推.有钱人就贿赂负责人,所以他们有一些好处

poj 1691 Painting A Board 拓扑序+dfs

题意: 一个木板上被分成了很多区域,每个区域要涂上一种特定的颜色,当涂一个区域的时候,它上方与它有重合部分的区域必须之前要涂好.求最少需要拿几次画笔(拿一次画笔可以涂颜色相同的多个区域). 分析: 上方与它有重合部分的区域必须之前要涂好这个限制可以用拓扑序来描述,每次涂有很多种可以涂的颜色,dfs就可以了.dfs的状态空间维数定为拿笔的次数,每次枚举可以涂的颜色.要注意的是dfs过程中要慎用全局变量..否则每个维度需枚举的东西被下一维改了就跪了... 代码: //poj 1691 //sep9

UVALive 6195 The Dueling Philosophers Problem 强连通缩点+拓扑序

题目链接:点击打开链接 给定n个点m条限制 下面限制 u->v 表示u必须排在v前面,问把n个数排成一排有多少种方法. 若有0种输出0 1种输出1 多种输出2 **边的数量题目里少了个0== 思路: 0种就是有环,缩点一下判断强连通分量是不是n个. 1种就是拓扑序时队列里任何时刻都只有一个点 否则就是2种 #pragma comment(linker, "/STACK:1024000000,1024000000") #include<stdio.h> #include

有史以来我最坑的一次,hdu5195 DZY Loves Topological Sorting 拓扑序

//这题可算是历经千辛万苦才算ac了 //建图,然后就拓扑序, //还是官方的bc的题解出的好 //贪心取编号最大的点 //令du[i]<=k的i进入优先队列 //然后依次整就行了, //每次取出的点,判断一下 //是否du[i]<=k,如果小于 //依次遍历与他相邻的点, //在这些相邻的点中找到du[j]<=k //且不在队列当中的i的值, //开始用g++交题,一直TLE, //用高效一点的邻接表,还是TLE //然后用c++交题,结果...ac了 //TLE了十多发... //发

codeforces 655D D. Robot Rapping Results Report(拓扑排序+拓扑序记录)

题目链接: D. Robot Rapping Results Report time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output While Farmer John rebuilds his farm in an unfamiliar portion of Bovinia, Bessie is out trying some alt

ZOJ 3795 Grouping 强联通缩点+拓扑序+偏序集的最大链的大小

题意:有n个人,m个关系,关系是这两个人前一个人可以跟后一个比较. 那么问你我最少分多少组可以使这个组里的人都不可以比较. 只会强联通缩点,真特么不知道怎么做,想了一个小时,网上一看,还要会偏序集的东西,有一个叫Dilworth定理的东西. 定理1 令(X,≤)是一个有限偏序集,并令r是其最大链的大小.则X可以被划分成r个但不能再少的反链. 其对偶定理称为Dilworth定理: 定理2 令(X,≤)是一个有限偏序集,并令m是反链的最大的大小.则X可以被划分成m个但不能再少的链. 然后我们用到的是

hdu5195 二分+线段树+拓扑序

这题说的给了n个点m条边要求保证是一个有向无环图,可以删除至多k条边使得这个图的拓扑序的字典序最大,我们知道如果我们要排一个点的时候一定要考虑比他大的点是否可以.通过拆边马上拆出来,如果可以拆当然是拆,肯定保证字典序最大,如果不能拆,就不拆留着以后拆,当初这个比他大的点度数小于k的,最大是多少,这个方法我一直想不出,后来看了题解,二分加线段树,可以做到,线段树维护每个点的d[i],然后通过二分找出小于k的最大点是多少. 1 #include <iostream> 2 #include <