拓扑排序总结

- 拓扑排序 hdu 1285

问题分析 怎么说呢 拓扑排序 给我的感觉就是 一棵树 从树冠 往下
每次遇到 比他的小的 就把它的入度+1 就往树下 走 然后从树冠 找
入度为0 是就是一个 小树冠 其下拥有若干 小树 小分支的入度为0 意味着到了
小树冠的底部但着并不意味着 这就是最小值 因为 可能还有比这个数的最大入度
还大的数存在

为了满足 不确定的 名次按照 队伍字典序排序
借助于优先队列来实现这个; 首先将 起始入度为0 的队伍加入 这意味着 树冠 (他们的 名词相对来说是靠前的单不能确定他们的具体名词 优先队列巴拉巴拉…)
然后 出队 扫描 分支 入度减一 存在 入度为0 就继续加入优先队列
具体代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define mem(a) memset(a,0,sizeof(a))
using namespace std;
int n,m,map[505][505],in[505];
int main()
{
	while(cin>>n>>m)
    {
    	mem(map);
		mem(in);
		while(m--)
		{
			int a,b;
			cin>>a>>b;
			if(!map[a][b])
			{
				map[a][b]=1;
			in[b]++;
			}
			
		 } 
	  priority_queue<int,vector<int>,greater<int> > q;
	  for(int i=1;i<=n;i++)
	  {
	  	if(!in[i])
	      q.push(i);
	  }
	  bool f=0;
	  while(q.size())
	  {
	  	int top=q.top();
	  	q.pop();
	  	in[top]--;
	  	if(!f)
		  cout<<top;
		else
		cout<<" "<<top;
		f=1;
		for(int i=1;i<=n;i++)
		{
			if(map[top][i])
			{
			in[i]--;
			if(!in[i])
		      q.push(i);	
			}  
		}
	  }
	  cout<<endl;
	}
    return 0;
}

H - 拓扑排序 (2) hdu 3342

问题分析 :
和上个 拓扑排序一样只不过是是反向查询 是否是存在循环结构 如果 存在就意味这有错误
而这在 程序中反映出来就是 查询值等于n;
具体代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define mem(a) memset(a,0,sizeof(a))
using namespace std;
int n,m,map[505][505],in[505];
int main()
{
     while(cin>>n>>m&&n&&m)
	 {     mem(map);
		   mem(in);
	 	for(int i=0;i<m;i++)
		 {
		 	int a,b;
		 	cin>>a>>b;
		 	if(!map[a][b])
		  {
		  	map[a][b]=1;
		  	in[b]++;
		  }
		  }
		   
		  int flag=0;
		  int i,j;
		  for( i=0;i<n;i++)
		  {
		  	for( j=0;j<n;j++)
		  	{
		  		if(!in[j])
		  		{
		  			in[j]--;
		  			for(int k=0;k<n;k++)
		  			{
		  				if(map[j][k])
					     in[k]--;
					}
					break;
				  }
			  }
			  if(j==n)
			  {
			  	flag=1;
			  break;	
			  } 
		  }
		  if(flag)
		  cout<<"NO\n";
		  else
		  cout<<"YES\n";
		  
	   }  
    return 0;
}

L - 拓扑排序 HDU 2647

就是拓扑排序 中间 加了一个 一888作为基值
代码如下:

#include<iostream>
#include<cstring>
#include<queue>
#include<vector>
#define mem(a)  memset(a,0,sizeof(a))
using namespace std;
int main()
{
 int n,m;
 while(cin>>n>>m)
{
 vector<int> map[20001];
 int in[10001],mo[10001];
 for(int i=1;i<=n;i++)
 map[i].clear();
 mem(in);
 queue<int> q;
 while(m--)
 {
 	int a,b;
 	cin>>a>>b;
 	map[b].push_back(a);
 	in[a]++;	   
 }
 for(int i=1;i<=n;i++)
    if(!in[i])
    {
    	q.push(i);
    	mo[i]=888;
    }
    
    int tot=0;
    int sum=0;
    while(!q.empty())
    {
    	int x=q.front();
    	sum+=mo[x];
    	tot++;
    	q.pop();
    	for(int i=0;i<map[x].size();i++)
 	   {
    		in[map[x][i]]--;
    		mo[map[x][i]]=mo[x]+1;
    		if(!in[map[x][i]])
    		q.push(map[x][i]);
 	   }    	   
    }
    if(tot<n)
    cout<<-1<<endl;
    else
    cout<<sum<<endl;	   
 }
 return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值