输入有若干组,每组中的第一行为二个数N(1<=N<=500),M;其中N表示队伍的个数,M表示接着有M行的输入数据。接下来的M行数据中,每行也有两个整数P1,P2表示即P1队赢了P2队。
给出一个符合要求的排名。输出时队伍号之间有空格,最后一名后面没有空格。
其他说明:符合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前;输入数据保证是正确的,即输入数据确保一定能有一个符合要求的排名。
4 3 1 2 2 3 4 3
1 2 4 3
#include <bits/stdc++.h>
using namespace std;
int main(){
int n,m;
while(cin>>n>>m){
vector<int> Edge[n+1];
int inDegree[n+1];
memset(inDegree,0,sizeof(inDegree));
for(int i=0;i<m;i++){
int a,b;
cin>>a>>b;
Edge[a].push_back(b);
inDegree[b]++;
}
priority_queue<int, vector<int>, greater<int>> Q;
for(int i=1;i<=n;i++)
if(inDegree[i]==0)
Q.push(i);
int cnt = 1;
while(!Q.empty()){
int u = Q.top();
Q.pop();
if(cnt==n)
cout<<u<<endl;
else
cout<<u<<" ";
cnt++;
for(int i=0;i<Edge[u].size();i++){
int v = Edge[u][i];
inDegree[v]--;
if(inDegree[v]==0)
Q.push(v);
}
}
}
return 0;
}
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
String str;
while ((str = bf.readLine()) != null) {
String[] line1 = str.split(" ");
int n = Integer.parseInt(line1[0]);//队伍的个数
int m = Integer.parseInt(line1[1]);//总共有m场比赛
//记录n个队伍比赛输掉的次数
int[] num1 = new int[n + 1];
PriorityQueue<Integer> queue = new PriorityQueue<>();
//记录第i个队伍赢得的队伍
HashMap<Integer, ArrayList<Integer>> map = new HashMap<>(m);
int a, b;
for (int i = 1; i <= m; i++) {
line1 = bf.readLine().split(" ");
a = Integer.parseInt(line1[0]);//赢比赛的队伍
b = Integer.parseInt(line1[1]);//输比赛的队伍
if (!map.containsKey(a)) {
map.put(a, new ArrayList<>());
}
map.get(a).add(b);
//eg:b队伍输的次数加一
num1[b]++;
}
for (int i = 1; i <= n; i++) {//将那些没有输过比赛的队伍加到优先队列中,题目要求相同排名的编号小的放在前面
if (num1[i] == 0) queue.add(i);
}
//保存输出结果
StringBuilder sb = new StringBuilder();
while (!queue.isEmpty()) {
int top = queue.poll();
sb.append(top);
sb.append(" ");
for (int i = 0; map.containsKey(top) && i < map.get(top).size(); i++) {
int x = map.get(top).get(i);
num1[x]--;
if (num1[x] == 0) queue.add(x);
}
}
sb.substring(0,sb.length()-1);
System.out.println(sb.toString());
}
}
}
""""
每次找到在第一列且不在第二列,或没有比赛结果的队伍,
输出最小编号,删除包含此最小编号队伍的比赛结果,重复上一步骤。
优化时间复杂度,优化比赛结果的存储格式,设置各队伍的入度(输的数量),可以用优先级队列进一步优化
"""
import sys
if __name__ == "__main__":
# sys.stdin = open("input.txt", "r")
try:
while True:
n, m = map(int, input().strip().split())
edge = [[] for _ in range(n + 1)]
indegree = [0] * (n + 1)
for _ in range(m):
a, b = map(int, input().strip().split())
edge[a].append(b)
indegree[b] += 1
pre = []
ans = []
for i in range(1, n + 1):
if indegree[i] == 0:
pre.append(i)
while pre:
ans.append(min(pre))
pre.remove(ans[-1])
for k in edge[ans[-1]]:
indegree[k] -= 1
if indegree[k] == 0:
pre.append(k)
print(' '.join(map(str, ans)))
except:
pass import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.HashMap;
import java.util.PriorityQueue;
public class Main{
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line;
while((line = br.readLine()) != null){
String[] params = line.split(" ");
int n = Integer.parseInt(params[0]);
int m = Integer.parseInt(params[1]);
// 图的邻接表
HashMap<Integer, LinkedList<Integer>> graph = new HashMap<>();
// 入度表
int[] inDegree = new int[n + 1];
for(int i = 0; i < m; i++){
params = br.readLine().trim().split(" ");
int p1 = Integer.parseInt(params[0]), p2 = Integer.parseInt(params[1]);
inDegree[p2]++;
if(graph.containsKey(p1)){
graph.get(p1).add(p2);
}else{
LinkedList<Integer> neighbors = new LinkedList<>();
neighbors.add(p2);
graph.put(p1, neighbors);
}
}
// 找到没有入度的队伍作为起点
PriorityQueue<Integer> queue = new PriorityQueue<>();
for(int i = 1; i <= n; i++){
if(inDegree[i] == 0){
queue.offer(i);
}
}
// 拓扑排序
String rank = topologicalSort(graph, queue, inDegree);
System.out.println(rank);
}
}
private static String topologicalSort(HashMap<Integer, LinkedList<Integer>> graph, PriorityQueue<Integer> queue, int[] inDegree) {
StringBuilder path = new StringBuilder();
// 拓扑排序
while(!queue.isEmpty()){
int cur = queue.poll();
path.append(cur).append(" ");
if(graph.containsKey(cur)){
Iterator<Integer> neighbors = graph.get(cur).iterator();
while(neighbors.hasNext()){
int next = neighbors.next();
inDegree[next]--;
if(inDegree[next] == 0){
queue.offer(next);
}
}
}
}
return path.toString().trim();
}
} #include <iostream>
#include <vector>
#include <queue>
using namespace std;
vector<int> edge[501]; // 邻接链表
priority_queue<int, vector<int>, greater<int> > Q;
int ans[501];
int inDegree[501];
int main(){
int n, m;
while(scanf("%d%d", &n, &m) != EOF)
{
// 初始化
for(int i = 1; i <= n; i++){
inDegree[i] = 0;
edge[i].clear();
}
for(int i = 0; i < m; i++)
{
int a, b;
scanf("%d%d", &a, &b);
inDegree[b]++;
edge[a].push_back(b);
}
while(Q.empty()==false) Q.pop();
for(int i = 0; i < n; i++)
ans[i] = 0;
for(int i = 1; i <= n; i++){
if(inDegree[i] == 0) Q.push(i);
}
int cnt = 0;
while(Q.empty()==false){
int node = Q.top();
ans[cnt++] = node;
Q.pop();
for(int i = 0; i < edge[node].size(); i++)
{
inDegree[edge[node][i]]--;
if(inDegree[edge[node][i]] == 0)
Q.push(edge[node][i]);
}
}
for(int i = 0; i < n-1; i++)
printf("%d ", ans[i]);
printf("%d\n", ans[n-1]);
}
return 0;
}
拓扑排序问题。
注意:因为相同名次的情况下,编号小的在前,所以需要使用优先队列。
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()) {
int n = sc.nextInt();
int m = sc.nextInt();
int[][] arr = new int[m][2];
int[] degrees = new int[n + 1];
for(int i = 0; i < m; i ++) {
arr[i][0] = sc.nextInt();
arr[i][1] = sc.nextInt();
degrees[arr[i][1]] ++;
}
PriorityQueue<Integer> queue = new PriorityQueue<>();
for(int i = 1; i <= n; i ++) {
if(degrees[i] == 0) queue.offer(i);
}
List<String> res = new ArrayList<>();
while(!queue.isEmpty()) {
int cur = queue.poll();
res.add(String.valueOf(cur));
for(int[] a : arr) {
if(a[0] != cur) continue;
if(-- degrees[a[1]] == 0) queue.offer(a[1]);
}
}
System.out.println(String.join(" ", res));
}
}
}
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
const int N=10000;
vector<int> edge[520];
priority_queue<int, vector<int>, greater<int>> Q; //小顶堆
int inDegree[N];
int n,m;
int main() {
while(scanf("%d%d",&n,&m)!=EOF) {
for(int i=1;i<=n;i++) {
inDegree[i]=0;
edge[i].clear();
}
while(m--) {
int a,b;
scanf("%d%d",&a,&b);
inDegree[b]++;
edge[a].push_back(b);
}
while(Q.empty()==false) Q.pop();
for(int i=1;i<=n;i++) {
if(inDegree[i]==0) Q.push(i);
}
int cnt=1;
while(Q.empty()==false) {
int nowP=Q.top();
Q.pop();
if(cnt==n)
cout<<nowP<<endl;
else
cout<<nowP<<" ";
cnt++;
for(int i=0;i<edge[nowP].size();i++) {
inDegree[edge[nowP][i]]--;
if(inDegree[edge[nowP][i]]==0) Q.push(edge[nowP][i]);
}
}
}
} 根据当前节点的入度判断排名在该节点以前的点是否都已经完成排序
#include<bits/stdc++.h>
using namespace std;
vector<int> Sort(vector<vector<int>> AdjList,vector<int> &inDegree){
vector<int> ans(AdjList.size(),0);
priority_queue<int, vector<int>, greater<int> > Q;
for (int i = 1; i <inDegree.size();i++){
if (!inDegree[i])
Q.push(i);
}
int cnt = 0;
while(!Q.empty()){
int cur = Q.top();
Q.pop();
cnt += 1;
ans[cnt] = cur;
for(auto &n:AdjList[cur]){
inDegree[n]--;
if(inDegree[n]==0){
Q.push(n);
}
}
}
return ans;
}
int main(){
int N, M;
while (cin>>N>>M)
{
vector<vector<int>> AdjList;
AdjList.resize(N + 1);
vector<int> inDegree(N + 1,0);
int fa, son;
for (int i = 0; i < M;i++){
cin >> fa >> son;
AdjList[fa].push_back(son);
inDegree[son] += 1;
}
vector<int> ans = Sort(AdjList,inDegree);
for (int i = 1; i < ans.size()-1;i++)
{
cout << ans[i] << " ";
}
cout << ans[ans.size() - 1] << endl;
}
return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int maxn = 500;
int indegree[maxn];
vector<int> graph[maxn];
void topologicalsort(int n){
priority_queue<int,vector<int>,greater<int> > q;
for(int i=1;i<=n;i++)
if(indegree[i]==0)
q.push(i);
while(!q.empty()){
int u = q.top();
q.pop();
cout<<u<<" ";
for(int i=0;i<graph[u].size();i++){
int v = graph[u][i];
indegree[v]--;
if(indegree[v] == 0)
q.push(v);
}
}
}
int main(){
int n,m;
while(cin>>n>>m){
if(n == 0 && m == 0)
break;
int from,to;
memset(graph,0,sizeof(graph));
memset(indegree,0,sizeof(indegree));
for(int i=1;i<=m;i++){
cin>>from>>to;
graph[from].push_back(to);
indegree[to]++;
}
topologicalsort(n);
}
}
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <cstring>
#include <functional>
using namespace std;
const int N = 510;
int a[N];
int n,m;
int degree[N];
bool visit[N];
vector<int> v[N];
int main()
{
while(cin >> n >> m)
{
for(int i = 0; i < m; i++)
{
int n = 0;
int m = 0;
cin >> n >> m;
v[n].push_back(m);
degree[m]++;
}
// priority_queue<int,vector<int>, greater<int>> q;
queue<int> q;
vector<int> res;
vector<int> tmp;
for(int i = 1; i <= n; i++)
{
if(degree[i] == 0)
{
q.push(i);
visit[i] = true;
break; //注意break;
}
}
/*
sort(tmp.begin(),tmp.end());
res = tmp;
tmp.clear();
*/
while(q.size())
{
int sz = q.size();
while(sz--)
{
auto tmp = q.front();
q.pop();
res.push_back(tmp);
for(int i = 0; i < v[tmp].size(); i++)
{
degree[v[tmp][i]]--;
}
}
for(int i = 1; i <= n; i++)
{
if(degree[i] == 0 && visit[i] != true)
{
q.push(i);
visit[i] = true;
break; //注意break
}
}
}
for(auto e: res)
{
cout << e << " " ;
}
cout << endl;
memset(v,0, sizeof v);
memset(visit,false, sizeof visit);
memset(degree,false, sizeof degree);
}
} //我只是代码的搬运工!!
#include<iostream>
(720)#include<cstring>
#include<vector>
(721)#include<queue>
using namespace std;
const int MAXN = 500 + 10;
vector<int> graph[MAXN];
int inDegree[MAXN];
vector<int> TopologicalSort(int n)
{
vector<int> answer;
priority_queue<int, vector<int>, greater<int> > node;
for(int i = 1; i <= n; ++i)
{
if(inDegree[i] == 0)
{
node.push(i);
}
}
while(!node.empty())
{
int current = node.top();
answer.push_back(current);
node.pop();
for(int i = 0; i < graph[current].size(); ++i)
{
int temp = graph[current][i];
inDegree[temp]--;
if(inDegree[temp] == 0)
{
node.push(temp);
}
}
}
return answer;
}
int main()
{
int n, m;
while(cin>>n>>m)
{
memset(graph, 0, sizeof(graph));
memset(inDegree, 0, sizeof(inDegree));
while(m--)
{
int from, to;
cin>>from>>to;
graph[from].push_back(to);
inDegree[to]++;
}
vector<int> answer = TopologicalSort(n);
for(int i = 0; i < answer.size(); ++i)
{
if(i == 0)
{
cout<<answer[i];
}
else
{
cout<<" "<<answer[i];
}
}
cout<<endl;
}
return 0;
}
from collections import defaultdict
from queue import PriorityQueue
while True:
try:
m,n = map(int,input().split())
qzero = PriorityQueue()
graph = defaultdict(list)
weight = [0]*(m+1)
for i in range(n):
a,b = map(int,input().split())
weight[b] += 1
graph[a].append(b)
for i in range(1,m+1):
if weight[i]==0:
qzero.put(i)
ans = []
while not qzero.empty():
node = qzero.get()
ans.append(node)
for index in graph[node]:
weight[index] -= 1
if weight[index] == 0:
qzero.put(index)
ans = list(map(str,ans))
print(' '.join(ans))
except:
break
#include<stdio.h>
int main(){
int n,m;
int res[505][505];
int in[505];
int ans[505];int p=0;
while(scanf("%d%d",&n,&m)!=EOF){
p=0;
for(int i=0;i<505;i++){
in[i]=0;
for(int j=0;j<505;j++)
res[i][j]=0;
}
if(n==0) break;
for(int i=0;i<m;i++){
int a,b;
scanf("%d %d",&a,&b);
res[a][b]=1;
in[b]++;
}
while(1){
int flag=0;
for(int i=1;i<=n;i++){
if(in[i]==0){
in[i]=-1;
ans[p++]=i;
for(int j=1;j<=n;j++){
if(res[i][j]==1){
in[j]--;
flag=1;
}
}
}
if(flag==1) break; //从i=1开始
}
if(flag==0) break;
}
for(int i=0;i<n;i++){
printf("%d ",ans[i]);
}
printf("\n");
}
} #include<bits/stdc++.h>//拓扑排序
using namespace std;
vector<int>edge[501];//存储节点及后继关系
priority_queue<int,vector<int>,greater<int> >Q;//存储入度为0的点,编号由小到大
int main()
{
int N,M;
int inDegree[501];//统计每个节点的入度
while(cin>>N>>M)
{
//初始化所有节点的入度和链接情况
for(int i=1;i<=N;i++)
{
inDegree[i]=0;
edge[i].clear();
}
while(M--){
int a,b;
cin>>a>>b;
inDegree[b]++;
edge[a].push_back(b);//a的后继是b
}
while(!Q.empty()) Q.pop();
//将入度为0的点放入队列
for(int i=1;i<=N;i++){
if(inDegree[i]==0)
Q.push(i);
}
//对入度为0的点进行遍历
int cnt=0;
while(!Q.empty())
{
int tmp=Q.top();//如果要求拓扑序列,就将tmp存入另一队列中
Q.pop();
cnt++;
if(cnt==N) cout<<tmp<<endl;//最后一个数
else cout<<tmp<<" ";
for(int i=0;i<edge[tmp].size();i++)
{
int tmpp=edge[tmp][i];//tmp的后继节点
inDegree[tmpp]--;
if(inDegree[tmpp]==0)
Q.push(tmpp);
}
}
}
return 0;
}