hdoj1285 确定比赛名次 topo排序 Kahn算法 (新手向)
来源:互联网 发布:ios矩阵潜袭 编辑:程序博客网 时间:2024/04/29 03:11
题目:
确定比赛名次
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 25983 Accepted Submission(s): 10468
其他说明:符合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前;输入数据保证是正确的,即输入数据确保一定能有一个符合要求的排名。
4 31 22 34 3
1 2 4 3
第一道拓扑排序的题,让我酝酿一下自己的情感,叫出“hello,world!”
什么是拓扑排序?
有向图的拓扑排序或拓扑排序是其顶点的线性排序,使得对于从顶点 u 到顶点 v 的每个有向边 uv,u 在排序中都在 v 之前。---来自维基百科
大概就是这样一个问题,你穿衣服,有鞋,裤子,袜子,衬衣。你先穿哪一个的问题。就是说,你执行的任务有一个先后顺序。对这些任务的执行顺序进行排序。争对上面这个问题,肯定是先裤子,再袜子,再鞋。衬衣这几个的关系倒无所谓,想啥时候穿,就啥时候穿。(这个涉及到全序,偏序的概念)
什么条件才能进行拓扑排序?
有向无环图(DAG, Directed Acyclic Graph)。这个也很好理解,比如我告诉你A在B前,B在A前,你该怎么排?从而topo排序,另外一个用法就是判断有没有环。
怎么topo排序?
这里的是Kahn算法,还有基于dfs的也可以摆渡一下。
Kahn算法的描述:
L← Empty list that will contain the sorted elements
S ← Set of all nodes with no incoming edges
while S is non-empty do
remove a node n from S
insert n into L
foreach node m with an edge e from nto m do
remove edge e from thegraph
ifm has no other incoming edges then
insert m into S
if graph has edges then
return error (graph has at least onecycle)
else
return L (a topologically sortedorder)
我们需要维护一个入度为0的集合S,然后取出S中一个点,删除所有与之相邻的边,相应的这些边指向的点的入度应该减少1,如果入度为0,则加入S。
判环:就是当最后S为空,而还剩余了图时就有环了。一切尽在上面的那段说明中。
复杂度:O(V+E)
code(基于hdoj1285):
对了,这道题,要求满足条件序号最小。那么就用优先队列搞搞就可以了。
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int MAXN=500+10;
int map[MAXN][MAXN];
int indegree[MAXN];
vector<int>G[MAXN];
int main(void){
int N,M;
while(~scanf("%d%d",&N,&M)){
priority_queue<int,vector<int> ,greater<int> >q;
while(!q.empty())q.pop();
memset(map,0,sizeof(map));
memset(indegree,0,sizeof(indegree));
for(int i=0;i<M;++i){
int a,b;scanf("%d%d",&a,&b);
if(!map[a][b]){//为了防止重边
map[a][b]=1;
G[a].push_back(b);
indegree[b]++;
}
}
for(int i=1;i<=N;++i)
if(indegree[i]==0)q.push(i);
bool isFirst=true;//为了满足格式要求
while(!q.empty()){
int no=q.top();q.pop();
printf(isFirst?"%d":" %d",no);
isFirst=false;
for(int i=0;i<G[no].size();++i){
int v=G[no][i];
indegree[v]--;
if(indegree[v]==0)q.push(v);
}
G[no].clear();//删除所有no指向的边
}
printf("\n");
}
}
————————介于WA与AC之间的分割线———————————————————————————————
关于偏序与全序:
一下内容转自:dm_vincent 侵删
偏序/全序关系:
偏序和全序实际上是离散数学中的概念。
这里不打算说太多形式化的定义,形式化的定义教科书上或者上面给的链接中就说的很详细。
还是以上面选课的例子来描述这两个概念。假设我们在学习完了算法这门课后,可以选修机器学习或者计算机图形学。这个或者表示,学习机器学习和计算机图形学这两门课之间没有特定的先后顺序。因此,在我们所有可以选择的课程中,任意两门课程之间的关系要么是确定的(即拥有先后关系),要么是不确定的(即没有先后关系),绝对不存在互相矛盾的关系(即环路)。以上就是偏序的意义,抽象而言,有向图中两个顶点之间不存在环路,至于连通与否,是无所谓的。所以,有向无环图必然是满足偏序关系的。
理解了偏序的概念,那么全序就好办了。所谓全序,就是在偏序的基础之上,有向无环图中的任意一对顶点还需要有明确的关系(反映在图中,就是单向连通的关系,注意不能双向连通,那就成环了)。可见,全序就是偏序的一种特殊情况。回到我们的选课例子中,如果机器学习需要在学习了计算机图形学之后才能学习(可能学的是图形学领域相关的机器学习算法……),那么它们之间也就存在了确定的先后顺序,原本的偏序关系就变成了全序关系。
实际上,很多地方都存在偏序和全序的概念。
比如对若干互不相等的整数进行排序,最后总是能够得到唯一的排序结果(从小到大,下同)。这个结论应该不会有人表示疑问吧:)但是如果我们以偏序/全序的角度来考虑一下这个再自然不过的问题,可能就会有别的体会了。
那么如何用偏序/全序来解释排序结果的唯一性呢?
我们知道不同整数之间的大小关系是确定的,即1总是小于4的,不会有人说1大于或者等于4吧。这就是说,这个序列是满足全序关系的。而对于拥有全序关系的结构(如拥有不同整数的数组),在其线性化(排序)之后的结果必然是唯一的。对于排序的算法,我们评价指标之一是看该排序算法是否稳定,即值相同的元素的排序结果是否和出现的顺序一致。比如,我们说快速排序是不稳定的,这是因为最后的快排结果中相同元素的出现顺序和排序前不一致了。如果用偏序的概念可以这样解释这一现象:相同值的元素之间的关系是无法确定的。因此它们在最终的结果中的出现顺序可以是任意的。而对于诸如插入排序这种稳定性排序,它们对于值相同的元素,还有一个潜在的比较方式,即比较它们的出现顺序,出现靠前的元素大于出现后出现的元素。因此通过这一潜在的比较,将偏序关系转换为了全序关系,从而保证了结果的唯一性。
拓展到拓扑排序中,结果具有唯一性的条件也是其所有顶点之间都具有全序关系。如果没有这一层全序关系,那么拓扑排序的结果也就不是唯一的了。在后面会谈到,如果拓扑排序的结果唯一,那么该拓扑排序的结果同时也代表了一条哈密顿路径。
偏序只对部分元素成立关系R,全序对集合中任意两个元素都有关系R.
例如:
集合的包含关系就是半序,也就是偏序,因为两个集合可以互不包含;
而实数中的大小关系是全序,两个实数必有一个大于等于另一个;
又如:复数中的大小就是半序,虚数不能比较大小.
- hdoj1285 确定比赛名次 topo排序 Kahn算法 (新手向)
- hdoj1285 确定比赛名次(topo序列)模板
- hdu1285确定比赛名次(拓扑排序kahn算法)
- HDOJ1285 确定比赛名次
- <hdoj1285>确定比赛名次
- hdoj1285-确定比赛名次
- HDOJ1285 确定比赛名次(拓扑排序)
- HDOJ1285 确定比赛名次(拓扑排序)
- 确定比赛名次--topo
- hdoj1285 确定比赛名次 (经典拓扑排序) 初学拓扑排序.做
- hdu 1285 确定比赛名次 topo
- 杭电-1285确定比赛名次(topo)
- 拓扑排序-- 确定比赛名次
- HDU 1285 确定比赛名次(拓扑排序算法)
- HDOJ 1285:确定比赛名次 拓扑排序
- 【拓扑排序】 hdu1285 确定比赛名次
- hdu 确定比赛名次(拓扑排序)
- 确定比赛名次(拓扑排序)
- 浅谈javaScript中slice和splice之间的区别和联系
- 图片
- JAVA基础知识中INT与String类型的转换
- 光盘yum源搭建
- 插入排序
- hdoj1285 确定比赛名次 topo排序 Kahn算法 (新手向)
- 算法设计作业16
- 每日分享之《破相》
- Metasploit为什么选择Ruby语言(部分)
- c++读入优化
- 169. Majority Element
- Linux Socket详解 <大全> 基础知识
- Python超越函数积分运算以及绘图实现
- 594. Longest Harmonious Subsequence