拓扑排序入门 基础
Posted 1starfish
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了拓扑排序入门 基础相关的知识,希望对你有一定的参考价值。
早上学了拓扑排序中最基础的一题,教的是用vector写的 然后自己刚刚用链式前向星写了一遍
拓扑排序就是先找出度为0的点然后放入队列,再把与这个点相连的点的度减一,如果度变成了0就在放进队列里面,直到队列变为空。
判断这个图是否无环 就用sum=0,每次进去就sum++,如果最后sum==n说明是无环的。
拓扑排序的裸题:
确定比赛名次
TimeLimit: 2000/1000 MS (Java/Others) MemoryLimit: 65536/32768 K (Java/Others)
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
给出一个符合要求的排名。输出时队伍号之间有空格,最后一名后面没有空格。
其他说明:符合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前;输入数据保证是正确的,即输入数据确保一定能有一个符合要求的排名。
其他说明:符合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前;输入数据保证是正确的,即输入数据确保一定能有一个符合要求的排名。
SampleInput
4 3 1 2 2 3 4 3
SampleOutput
1 2 4 3
第一种 vector写法:
#include<stdio.h> #include<string> #include<string.h> #include<set> #include<queue> #include<math.h> #include<stack> #include<vector> #include<map> #include<cmath> #include<stdlib.h> #include<algorithm> using namespace std; #define ll long long #define mes(x,a) memset(x,a,sizeof(x)) const int maxn=1e3+3; const int inf=0x3f3f3f3f; vector<int>a[maxn]; int n,m; int degree[maxn]; void init() { mes(degree,0); for(int i=0; i<=n; i++) a[i].clear(); } void topo() { int i,j,t; priority_queue<int>que; for(int i=1; i<=n; i++) if(degree[i]==0) que.push(-i); int flag=1; while(!que.empty()) { if(!flag) printf(" "); if(flag) flag=0; int now=-que.top(); que.pop(); printf("%d",now); for(int i=0; i<a[now].size(); i++) { int y=a[now][i]; degree[y]--; if(degree[y]==0) que.push(-y); } } puts(""); } int main() { int i; while(scanf("%d%d",&n,&m)!=EOF) { init(); for(i=0; i<m; i++) { int u,v; scanf("%d%d",&u,&v); a[u].push_back(v); degree[v]++; } topo(); } return 0; }
第二种链式前向星写法:
#include<stdio.h> #include<string> #include<string.h> #include<set> #include<queue> #include<math.h> #include<stack> #include<vector> #include<map> #include<cmath> #include<stdlib.h> #include<algorithm> using namespace std; const int maxn=1e3+5; int n,m; int first[maxn],sign; int degree[maxn]; struct Edge { int to; int w; int next; } edge[maxn]; void init() { sign=0; memset(first,-1,sizeof(first)); memset(edge,0,sizeof(edge)); } void add_edge(int u,int v,int w) { edge[sign].to=v; edge[sign].w=w; edge[sign].next=first[u]; first[u]=sign++; } void topo() { priority_queue<int,vector<int >, greater<int > >que; ///小根堆 for(int i=1; i<=n; i++) { if(degree[i]==0) que.push(i); } int flag=0; while(!que.empty()) { int now=que.top(); que.pop(); if(flag==1) { printf(" "); } flag=1; printf("%d",now); for(int i=first[now]; ~i; i=edge[i].next) { int to=edge[i].to; degree[to]--; ///与now相连的点的度减一,如果==1就放进队列 if(degree[to]==0) { que.push(to); } } } puts(""); } int main() { while(~scanf("%d %d",&n,&m)) { init(); for(int i=1; i<=m; i++) { int u,v; scanf("%d %d",&u,&v); add_edge(u,v,1); degree[v]++;///度增加 } topo(); } }
以上是关于拓扑排序入门 基础的主要内容,如果未能解决你的问题,请参考以下文章