传送门

确定比赛名次

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 17915    Accepted Submission(s): 7169

Problem 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表示即P1队赢了P2队。
 
Output
给出一个符合要求的排名。输出时队伍号之间有空格,最后一名后面没有空格。
其他说明:符合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前;输入数据保证是正确的,即输入数据确保一定能有一个符合要求的排名。
 
Sample Input
4 3
1 2
2 3
4 3
 
Sample Output
1 2 4 3
 
Author
SmallBeer(CML)
 
Source
 
Recommend
lcy
-------------------------------------------------------------------------------------------------------------------------
我的错误解法

#include <bits/stdc++.h>
using namespace std;
const int N(+);
vector<int> g[N];
bool vis[N];
int topo[N], tot;
void dfs(int u){
vis[u]=;
for(int i=; i<g[u].size(); i++){
int &v=g[u][i];
if(vis[v]) continue;
dfs(v);
}
topo[--tot]=u;
}
int main(){
for(int n, m; ~scanf("%d%d", &n, &m);){
for(int i=; i<=n; i++) g[i].clear();
for(int u, v; m--;) scanf("%d%d", &u, &v), g[u].push_back(v);
for(int i=; i<=n; i++) sort(g[i].begin(), g[i].end(), greater<int>());
memset(vis, , sizeof(vis)); tot=n;
for(int i=n; i; i--) if(!vis[i]) dfs(i);
printf("%d", topo[]); for(int i=; i<n; i++) printf(" %d", topo[i]); puts("");
}
}
首先总的想法是DFS拓扑排序,由于题目要求输出字典序最小的排列,对DFS的顺序做一些修改:
(1)将每个节点的邻接表从大到小排序
(2)在主函数内,按照节点编号从大到小的顺序调用DFS
这两个修改虽然方向是对的,但还是有问题的。
比如,样例
5 4
5 2
2 4
5 3 
3 1
正确输出是
5 2 3 1 4
但我的代码输出:
5 2 4 3 1
这个题目的输出要解决的问题是:
保证先后关系不确定的节点中,序号小的在前。
(注意,上面用的词是先后关系,而非胜负关系。因为,假如知道了 A胜B, B胜C 那么A, B, C三者的先后一定是 A B C 但A和C的胜负关系是不知道的。)
能否在不改变DFS框架的前提下,使输出正确呢?
 ---------------------------------------------------------------------------------------
正解是:迭代
每次选择入度为0且编号最小的点u输出,将u删除,并将u的临接表中的点的入度减一。
(这种解法不需要处理重边)
 
#include <bits/stdc++.h>
using namespace std;
const int N(+);
vector<int> g[N];
int in[N];
int main(){
for(int n, m; ~scanf("%d%d", &n, &m);){
for(int i=; i<=n; i++) g[i].clear();
memset(in, , sizeof(in));
for(int u, v; m--;) scanf("%d%d", &u, &v), g[u].push_back(v), in[v]++;
for(int i=; i<n; )
for(int u=; u<=n; u++){
if(in[u]==){
if(!i++) printf("%d", u);
else printf(" %d", u);
in[u]=-;
for(int j=; j<g[u].size(); j++){
int &v=g[u][j]; in[v]--;
}
break;
}
}
puts("");
}
}
还可用堆优化
#include <bits/stdc++.h>
using namespace std;
const int N(+);
vector<int> g[N];
int in[N];
typedef pair<int,int> P;
priority_queue<P, vector<P>, greater<P> > que;
int main(){
for(int n, m; ~scanf("%d%d", &n, &m);){
for(int i=; i<=n; i++) g[i].clear();
memset(in, , sizeof(in));
for(int u, v; m--;) scanf("%d%d", &u, &v), g[u].push_back(v), in[v]++;
for(int i=; i<=n; i++) que.push({in[i], i});
bool first=true;
while(!que.empty()){
P top=que.top(); que.pop(); int &u=top.second;
if(in[u]!=top.first) continue;
if(first) printf("%d", u), first=false;
else printf(" %d", u);
for(int i=; i<g[u].size(); i++){
int &v=g[u][i];
que.push({--in[v], v});
}
}
puts("");
}
}
 
 

HDU 1285 确定比赛名次的更多相关文章

  1. ACM: HDU 1285 确定比赛名次 - 拓扑排序

     HDU 1285 确定比赛名次 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u De ...

  2. HDU.1285 确定比赛名次 (拓扑排序 TopSort)

    HDU.1285 确定比赛名次 (拓扑排序 TopSort) 题意分析 裸的拓扑排序 详解请移步 算法学习 拓扑排序(TopSort) 只不过这道的额外要求是,输出字典序最小的那组解.那么解决方案就是 ...

  3. 正向与反向拓扑排序的区别(hdu 1285 确定比赛名次和hdu 4857 逃生)

    确定比赛名次 Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other) Total Submis ...

  4. HDU 1285 确定比赛名次(简单拓扑排序)

    题目链接: 传送门 确定比赛名次 Time Limit: 1000MS     Memory Limit: 65536K Description 有N个比赛队(1 Input 输入有若干组,每组中的第 ...

  5. hdu 1285 确定比赛名次 (拓扑)

    确定比赛名次 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  6. HDU 1285 确定比赛名次【字典序最小的拓扑排序 + 优先队列】

    确定比赛名次 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submis ...

  7. [ACM] hdu 1285 确定比赛名次 (拓扑排序)

    确定比赛名次 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  8. HDU——1285 确定比赛名次

    确定比赛名次 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  9. hdu 1285 确定比赛名次 (topsort)

    确定比赛名次Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submi ...

随机推荐

  1. localStorage实现购物车数量单价和总价实时同步(二)

    利用localStorage实时显示购物车小计和总价页面显示: 和昨天的原理相同,本地存储同时实时循环计算总价之和,注意循环时候的先清空再计算 Success is getting what you ...

  2. Qt——QLineEdit使用总结

    QLineEdit是一个单行文本编辑控件. 使用者可以通过很多函数,输入和编辑单行文本,比如撤销.恢复.剪切.粘贴以及拖放等. 通过改变QLineEdit的 echoMode() ,可以设置其属性,比 ...

  3. 在opencv3中利用SVM进行图像目标检测和分类

    采用鼠标事件,手动选择样本点,包括目标样本和背景样本.组成训练数据进行训练 1.主函数 #include "stdafx.h" #include "opencv2/ope ...

  4. 北京联想招聘-java 云服务开发工程师 加入qq 群:220486180 或者直接在此 留言咨询

     Position Title: 云服务开发工程师 Experience Required:  3 - 5 Years 负责联想企业网盘服务端开发  Position Requirements  1. ...

  5. Edittext焦点处理

    <LinearLayout android:focusable="true" android:layout_width="0dp" android:lay ...

  6. C语言学习的记忆

    优于他人的技能 会玩双截棍: 我的经验就是Practice make perfect,熟能生巧:还有就是坚持不懈. 关于C语言的学习的回忆 1.我通过老师的教导和课外C语言书籍中学习,和我的技能相比, ...

  7. eclipse的一些初始化设置

    eclipse下载地址:http://www.eclipse.org/ 添加java注释模板 codetemplates.xml:Window->Preferences->Java-> ...

  8. 导航栏全透明效果, 只保留左右两个按钮, 如何实现?以及关于NavigationController的小问题

    [self.navigationController.navigationBar setBackgroundImage:[UIImage imageWithColor:[UIColor clearCo ...

  9. 微软office web apps 服务器搭建之在线文档预览(一)

    office web apps安装 系统要求为Windows Server 2012, 注意:转换文档需要两台服务器,一台为转换server,另外一台为域控server.(至于为什么要两台,这个请自行 ...

  10. .NET MVC控制器向视图传递数据的四种方式

    .NET MVC控制器向视图传递数据的四种方式: 1.ViewBag  ViewBag.Mvc="mvc"; 2.ViewData ViewBag["Mvc"] ...