拓扑排序
来源:互联网 发布:union c语言应用实例 编辑:程序博客网 时间:2024/05/16 07:02
拓扑排序
源自:http://blog.csdn.net/u012860063?viewmode=contents
把每个变量看成一个点,“小于”关系看成有向边,则我们得到了一个有向图。这样,我们的任务实际上是把一个图的所有结点排序,使得每一条有向边(u,v)对应的u都排在v的前面。在图论中,这个问题称为拓扑排序。
不难发现:如果图中存在有向环,则不存在拓扑排序,反之则存在。我们把不包含有向环的有向图称为有向无环图。可以借助dfs函数完成拓扑排序:在访问完一个结点之后把它加到当前拓扑排序的首部。
一、输出任意一种满足优先条件的即可:
代码如下:
#include <cstdio>
#include <cstring>
#define MAXN 517
int G[MAXN][MAXN];
int c[MAXN],topo[MAXN];
int t;
int n, m;
bool dfs(int u)
{
c[u] = -1;
for(int v = 1; v <= n; v++)
{
if(G[u][v])
{
if(c[v] < 0)
return false;
else if(!c[v] && !dfs(v))
return false;
}
}
c[u] = 1;
topo[--t] = u;
return true;
}
bool toposort()
{
t = n;
memset(c,0,sizeof(c));
for(int u = 1; u <= n; u++)
{
if(!c[u])
{
if(!dfs(u))
return false;
}
}
return true;
}
int main()
{
int a, b;
int i;
while(~scanf("%d%d",&n,&m))
{
for(i = 0; i < m; i++)
{
scanf("%d%d",&a,&b);
G[a][b] = 1;
}
if(toposort())
{
bool ok = true;
for(i = 0; i < n; i++)
{
if(ok)
{
printf("%d",topo[i]);
ok = false;
}
else
printf(" %d",topo[i]);
}
}
printf("\n");
}
return 0;
}
二、输出满足条件且要求输出时字典序小的在前:
此时需要用到优先队列;
拓扑排序首先统计每个结点的入度。将度为0的结点编号放入队列(此题放入优先队列中)中。
然后进行循环:
取出队头结点,视作边的起点。
然后“删除与该点相连的边”,代码就是将这个图中的该边另一个结点(即终点)的入度减一;
如果减一以后,终点的入度变为了0,那么将终点的编号入队列。
判断队列是否为空,若不空,则回到1
优先队列
C++ STL中有优先队列的类——priority_queue<T>。默认优先队列是值越大,优先级越高。所以比如priority_queue<int> q。这里面的元素是降序排列的。如果我们要实现升序需要重载。
#include<iostream>
#include<queue>
#include<cstdio>
#include<cstring>
using namespace std;
bool map[517][517];
int in[517];
priority_queue<int,vector<int>,greater<int> > q;
void toposort(int n)
{
for(int i=1;i<=n;i++)
{
if(in[i]==0)//入度为0的放入队列中
q.push(i);
}
int c=1;
while(!q.empty())
{
int v=q.top();
q.pop();
if(c!=n)
{
cout<<v<<" ";
c++;
}
else
cout<<v<<endl;
for(int i=1;i<=n;i++)
{
if(!map[v][i])
continue;
in[i]--;
if(!in[i])//入度为0的放入队列
q.push(i);
}
}
}
int main()
{
int n,m,i,j;
while(cin>>n>>m)
{
int k=0;
memset(map,0,sizeof map);
memset(in,0,sizeof in);
while(m--)
{
cin>>i>>j;
if(map[i][j])//去重
continue;
map[i][j]=1;
in[j]++;
}
toposort(n);
}
}
- 拓扑排序
- 拓扑排序
- 拓扑排序
- 拓扑排序
- 拓扑排序
- 拓扑排序
- 拓扑排序
- 拓扑排序
- 拓扑排序
- 拓扑排序
- 拓扑排序
- 拓扑排序
- 拓扑排序
- 【拓扑排序】
- 拓扑排序
- 拓扑排序
- 拓扑排序
- 拓扑排序
- Oracle中修改表列名,用SQL语句的方式
- 验证new一个新对象是不加锁的操作,会导致出现null异常
- Web Service进阶(五)SOAPBinding方式讲解
- MATLAB相关系数计算
- .NET截取制定长度汉子超出部分以“...”代替
- 拓扑排序
- http和https,
- 单词翻转
- 汉诺塔
- 我不知道的C#—字符串池机制
- Dijkstra算法——最短路径(初步认识)
- Codeforces Round #118 (Div. 1) A Mushroom Scientists (多元函数极值问题+拉格朗日乘数法)
- POJ 3090-Visible Lattice Points(筛选法求欧拉函数)
- cocos2dx 使用过程中内存管理的理解