拓扑排序:
二.拓扑序列算法思想
(1)从有向图中选取一个没有前驱(即入度为0)的顶点,并输出之;
(2)从有向图中删去此顶点以及所有以它为尾的弧;
重复上述两步,直至图空,或者图不空但找不到无前驱的顶点为止。
三.代码实现
采用邻接矩阵实现,map[i][j]=0,表示节点i和j没有关联;map[i][j]=1,表示存在边<i,j>,并且j的入度加1;
#include<iostream>//复杂度高
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#define MAX 100
using namespace std;
void toposort(int map[MAX][MAX],int indegree[MAX],int n)
{
int i,j,k;
for(i=1;i<=n;i++) //遍历n次
{
for(j=1;j<=n;j++) //找出入度为0的节点
{
if(indegree[j]==0)
{
indegree[j]--;
cout<<j<<endl;//其中一种拓扑排序
for(k=1;k<=n;k++) //删除与该节点关联的边
{
if(map[j][k]==1)
{
indegree[k]--;
}
}
break;
}
}
}
}
int main(void)
{
int n,m; //n:关联的边数,m:节点数
while(scanf("%d %d",&n,&m)==2&&n!=0)
{
int i;
int x,y;
int map[MAX][MAX]; //邻接矩阵
int indegree[MAX]; //入度
memset(map,0,sizeof(map));
memset(indegree,0,sizeof(indegree));
for(i=1;i<=n;i++)
{
scanf("%d %d",&x,&y);
if(!map[x][y])
{
map[x][y]=1;
indegree[y]++;
}
}
toposort(map,indegree,m);
}
return 0;
}
复杂度低:
拓扑排序符合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
#define LL long long
using namespace std;
const int INF = 1e9+7;
const int VM = 503;//点的个数
struct node //前向星的结构体
{
int v;//输队编号
int next;
};
node edge[VM * 4];//结构体数组
int head[VM];//头指针数组
int cnt;//下标
int deg[VM];//入度数组
void toposort(int n)
{
priority_queue<int, vector<int>, greater<int> > que;//优先队列
for (int i = 1; i <= n; i++)//找所有点
if (deg[i] == 0) //入度为0
{
que.push(i);//加入队列
deg[i]--;//入度 变为-1
}
int k = 1;
while (que.empty() == false) //队列不为空
{
int u = que.top();//取出队首的数
que.pop();//删除
printf("%d%c", u, k++ == n ? '\n' : ' ');//输出
for (int i = head[u]; i != -1; i = edge[i].next) //与该点相连的
{
node e = edge[i];//便于书写
deg[e.v]--;//点的入度-1
if (deg[e.v] == 0)//若此点的 入度为 0
que.push(e.v);//放入队列
}
}
}
int main()
{
int n, m;
int i;
while (scanf("%d %d", &n, &m) == 2) //多组输入 ,获取n,m
{
memset(head, -1, sizeof(head));//初始化
memset(deg, 0, sizeof(deg));//初始化
cnt = 0;//初始化
while (m--)
{
int u, v;
scanf("%d %d", &u, &v);//获取u,v
for (i = head[u]; i != -1; i = edge[i].next)//查找重边
if (edge[i].v == v)//输入重复数据
break;//不再储存
if (i == -1) //若不是重复数据
{
deg[v]++;//加边
edge[cnt].v = v;
edge[cnt].next = head[u];
head[u] = cnt++;
}
}
toposort(n);//调用函数
bool fla=true;
for(int i=1; i<=n; i++)
{
if(deg[i]>0)
{
fla=false;
break;
}
}
if(!fla)
printf("youhuan\n");
else
printf("meihuan\n");
}
}
拓扑排序符合条件的排名可能不是唯一的,此时要求输出时编号大的队伍在前
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#include<vector>
using namespace std;
int main()
{
int rd[10000];
int top[10000];
vector<int>v[10000];
queue<int>q;
int n,m;
int cot;
scanf("%d%d",&n,&m);
//初始化
memset(rd,0,sizeof(rd));
for(int i=0;i<=n;i++)
v[i].clear();
cot=0;
//输入边
int x,y;
for(int i=0;i<m;i++)
{
scanf("%d%d",&x,&y);
rd[x]++;
v[y].push_back(x);
}
//找到入度为0入队列
for(int i=1;i<=n;i++)
{
if(rd[i]==0)
{
q.push(i);
rd[i]--;
top[cot++]=i;
}
}
while(!q.empty())
{
int k=q.front();
printf("%d\n",k);
q.pop();
for(int i=0;i<(int)v[k].size();i++)
{
int tep=v[k][i];
rd[tep]--;
if(rd[tep]==0)
{
q.push(tep);
top[cot++]=tep;
}
}
}
bool fla=true;
for(int i=1;i<=n;i++)
{
if(rd[i]>0)
{
fla=false;
break;
}
}
if(!fla)
printf("youhuan\n");
else
printf("meihuan\n");
}
练习:
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=105824#overview