您的位置:首页 > 其它

(hdu step 5.2.5)确定比赛名次(求拓扑序列)

2015-03-08 19:00 387 查看
题目:

确定比赛名次

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 337 Accepted Submission(s): 180
 
[align=left]Problem Description[/align]有N个比赛队(1<=N<=500),编号依次为1,2,3,。。。。,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得每个队的比赛成绩,只知道每场比赛的结果,即P1赢P2,用P1,P2表示,排名时P1在P2之前。现在请你编程序确定排名。 
[align=left]Input[/align]输入有若干组,每组中的第一行为二个数N(1<=N<=500),M;其中N表示队伍的个数,M表示接着有M行的输入数据。接下来的M行数据中,每行也有两个整数P1,P2表示即P1队赢了P2队。 
[align=left]Output[/align]
            给出一个符合要求的排名。输出时队伍号之间有空格,最后一名后面没有空格。

其他说明:符合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前;输入数据保证是正确的,即输入数据确保一定能有一个符合要求的排名。 
[align=left]Sample Input[/align]
4 3
1 2
2 3
4 3
 
[align=left]Sample Output[/align]
1 2 4 3
 
[align=left]Author[/align]SmallBeer(CML) 
[align=left]Source[/align]杭电ACM集训队训练赛(VII) 
[align=left]Recommend[/align]lcy 
题目分析:
               拓扑序列,简单题。
这里面也还有几道拓扑序列的题:http://blog.csdn.net/hjd_love_zzt/article/details/28700653

使用邻接矩阵AC的代码:
/*
* e1.cpp
*
* Created on: 2015年3月8日
* Author: Administrator
*/

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

const int maxn = 505;
int map[maxn][maxn];//连接情况.例如map[a][b]=1表示a与b连通
int indegree[maxn];//用于存储各点的入度
int queue[maxn];//最后的拓扑序列

int n;//点数
int m;//边数
int cnt;//拓扑序列中的节点数

/**
* 求拓扑序列
*/
void topo() {
int i;
int j;
int k;

for (i = 1; i <= n; ++i) {//枚举所有起点
for (j = 1; j <= n; ++j) {//枚举所有终点
if (indegree[j] == 0) {//如果某一终点的入度为0
indegree[j]--;//移除该点
queue[cnt++] = j;//将该点加入拓扑序列中

//将以该点为起点的所有边的终点的入度-1
for (k = 1; k <= n; ++k) {
if (map[j][k] != 0) {
indegree[k]--;
}
}

break;//这个一定要有,否则会wa。break只对本层循环起作用。不对if-esle语句起作用
}

//存在环的情况
if (j > n) {
cout << "存在环" << endl;
return;
}
}
}
}

int main() {
while (scanf("%d%d", &n, &m) != EOF) {
memset(indegree, 0, sizeof(indegree));
memset(map, 0, sizeof(map));
cnt = 0;

int i;
for (i = 0; i < m; ++i) {
int a, b;
scanf("%d%d", &a, &b);

if (map[a][b] == 0) {//去重.这道题可能存在重复数据。例如1 2这组数据出现多次
map[a][b] = 1;
indegree[b]++;
}
}

topo();

for (i = 0; i < cnt - 1; ++i) {
printf("%d ", queue[i]);
}
printf("%d\n", queue[cnt - 1]);
}

return 0;
}


使用链式前向星实现的拓扑排序,不过输出的顺序不符合这道题的题意,但是大家可以借此学一下
链式前向星的写法:
/*
* e.cpp
*
* Created on: 2015年3月8日
* Author: Administrator
*/

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

const int maxn = 501;
const int maxm = maxn * maxn;

struct edge {
int to;
int weight;
int next;
} edge[maxm];
int head[maxn];
int indegree[maxn];

int n, m;

void topo() {
int queue[maxn];
int iq = 0;

int i;
for (i = 1; i <= n; ++i) {
if (indegree[i] == 0) {
queue[iq++] = i;
}
}

for (i = 0; i < iq; ++i) {
int k;
for (k = head[queue[i]]; k != -1; k = edge[k].next) {
indegree[edge[k].to]--;
if (indegree[edge[k].to] == 0) {
queue[iq++] = edge[k].to;
}
}
}

for(i = 0 ; i <= iq-2 ; ++i){
printf("%d ",queue[i]);
}
printf("%d\n",queue[iq-1]);

// if (iq < n) { //如果iq的最终值小于n.说明拓扑序列不存在...
// printf("T_T\n");
// printf("%d\n", n - iq);
// } else {
// printf("o(∩_∩)o\n");
// }

}

int main() {
while (scanf("%d%d", &n, &m) != EOF) {
memset(head, -1, sizeof(head));
memset(indegree, 0, sizeof(indegree));

int cnt = 0;

int i;
for (i = 1; i <= m; ++i) {
int a;
int b;
scanf("%d%d", &a, &b);

indegree[b]++;
edge[cnt].to = b;
edge[cnt].next = head[a];
head[a] = cnt++;
}

topo();
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: