确定比赛名次-拓扑排序

题目链接:https://vjudge.net/problem/HDU-1285

邻接矩阵存储版

#include<iostream>
#include<queue>
#include<cstring>
#include<functional>
#include<vector>
using namespace std;
const int N = 510;
int n, m;

int g[N][N], in[N]; // in[i]记录i的入度数   g为邻接矩阵

void solve() {
	priority_queue<int, vector<int>, greater<int> > q;  // 使用小根堆(题目要求:符合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前)
	vector<int> ans;
	memset(g, 0, sizeof g);
	memset(in, 0, sizeof in);

	for (int i = 0; i < m; i ++) {
		int a, b;
		cin >> a >> b;
		if (g[a][b]) continue; // 用邻接矩阵注意重复边 
		g[a][b] = 1;
		in[b] ++;
	}

	for (int i = 1; i <= n; i ++)
		if (in[i] == 0) {
			q.push(i);

	while(!q.empty()) {
		int t = q.top();
		q.pop();
		ans.emplace_back(t);
		for (int i = 1; i <= n; i ++) {
			if (g[t][i] == 1) {
				in[i] --;
				if (in[i] == 0)
					q.push(i);
			}
		}
	}
	for (int i = 0; i < ans.size(); i ++) {
		if (i == 0) cout << ans[i];
		else cout << " " << ans[i];
	}
	cout << endl;
}


int main() {

	while(cin >> n >> m) {
		solve();
	}
	return 0;
}

邻接表版

#include <iostream>
#include <vector>
#include <queue>

using namespace std;

int main() {
	int n, m;
	while(cin >> n >> m) {
		vector<vector<int> > g(n + 1);
		vector<int> indegree(n + 1);

		// 符合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前
		priority_queue<int, vector<int>, greater<int> > heap; // 小顶堆

		// 初始图,并统计入度
		for (int i = 0; i < m; i ++) {
			int a, b;
			cin >> a >> b;
			g[a].push_back(b);
			indegree[b] ++;
		}
		// 将入度为零的加入小顶堆
		for (int i = 1; i <= n; i ++) 
			if(indegree[i] == 0) 
				heap.push(i);

		vector<int> ans; // ans 用于收集结果 
		while(!heap.empty()) {
			int t = heap.top();
			heap.pop();
			ans.emplace_back(t);
			// 更新入度数组 ,入度为零则加入队列 
			for (int i = 0; i < g[t].size(); i ++) { 
				indegree[g[t][i]] --;
				if (indegree[g[t][i]] == 0) {
					heap.push(g[t][i]);
				}
			}
		}
        for (int i = 0; i < ans.size(); i ++) {
            if (i == 0) cout << ans[i];
            else cout << " " << ans[i];
        }
        cout << endl;
	}

	return 0;
}

链式前向星版

#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
const int N = 550;
const int M = 2.5e5;
int n, m, idx;
int indegree[N];
int head[N];
struct edge {
	int to, next;
};
edge e[M];
void add(int a, int b) {
	e[idx].to = b;
	e[idx].next = head[a];
	head[a] = idx;
	idx++;
}
void init() {
	idx = 0;
	fill(head, head + N, -1);
}

void solve() {
	priority_queue<int, vector<int>, greater<int> > q;
	vector<int> ans;
	init();
	memset(indegree, 0, sizeof indegree);

	for (int i = 0; i < m; i ++) {
		int a, b;
		cin >> a >> b;
		add(a, b);
		indegree[b] ++;
	}

	for (int i = 1; i <= n; i ++)
		if (indegree[i] == 0)
			q.push(i);

	while(!q.empty()) {
		int t = q.top();
		q.pop();
		ans.emplace_back(t);
		for (int i = head[t]; ~i; i = e[i].next) {
			indegree[e[i].to] --;
			if (indegree[e[i].to] == 0) {
				q.push(e[i].to);
			}
		}
	}
	for (int i = 0; i < ans.size(); i ++) {
		if (i == 0) cout << ans[i];
		else cout << " " << ans[i];
	}
	cout << endl;
}


int main() {

	while(cin >> n >> m) {
		solve();
	}
	return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值