您的位置:首页 > 其它

HDU 1285 确定比赛名次(拓扑排序模板)

2014-08-06 08:25 218 查看
题意还是比较容易理解的,关键要看到后面的:合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前;

思路:这道题就是拓扑排序的经典应用了,用队列做的考虑优先编号小的出队就可以了。

拓扑排序:

拓扑排序是对有向无回路图(DAG)顶点的一种排序,它使得如果存在从u到v的有向路径,那么满足序列中u在v前。
所以我们的算法可以描述为这样一个过程:
1、找到整个图中所有的度为0的点,将这些点压进队列(栈)中
2、从队列(栈)中取出一点,输出,将该点及它的边删除,找到它所指向的点,如果改点是一个原点(删除指向它的点后),则压入队列(栈)
3、重复2过程,直到它为空

注:所谓度为0,即没有子节点,为1则只有一个,为2则有2个。为什么要先让度为0的点出来?因为你在定义的时候,度为0的点,则说明其没有父节点,即没有人排在它的前面!

所以基本AC代码:
#include<iostream>
#include<cstring>
using namespace std;
int map[502][502],flag[502],m,n,val[502];
void topsort()
{
	int i, j, k=1;
	for(i=1; i<=n; i++) //有n个点,所以要找n次
	{
		for(j=1; j<=n; j++)    
		{
			if(flag[j]==0)  //循环寻找度为0的点
			{
				flag[j]--;
				val[k++]=j;
				for(int x=1; x<=n; x++) //删除指向该点的边
					if(map[j][x])
						flag[x]--;  //使其度为0
				break;
			}
			if(j>n)
				return ;
		}
	}
}
int main()
{
	int i,j;
	while(cin>>n>>m)
	{
		memset(map,0,sizeof(map));
		memset(flag,0,sizeof(flag));    //初始化所有的点的度为0
		int a,b;
		for(i=1;i<=m;i++)
		{
			cin>>a>>b;
			if(!map[a][b])
			{
				map[a][b]=1;
				flag[b]++;  //度增加
			}
		}
		topsort();
		for(i=1;i<=n; i++)
			if(i!=n)
				cout<<val[i]<<" ";
			else
				cout<<val[i]<<endl;
	}
	return 0;
}


优先队列优化后的代码:

#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
const int N=510+10;
vector<int> g
;   //邻接表
int du
,val
;   
int n,m;
void  topsort()
{
    int i;
    priority_queue<int, vector<int>, greater<int> > q;//定义一个优先队列,并定义编号小的优先出队
    for(i=1;i<=n;i++)
        if(!du[i])
            q.push(i);
    int cnt=1;
    while(!q.empty())
    {
        int u=q.top();
        q.pop();
        val[cnt++]=u;
        for(i=0;i<g[u].size();i++)
        {
            int v=g[u][i];
            du[v]--;
            if(!du[v])
                q.push(v);
        }
    }
}
int main()
{
    int i,j,u,v;
    while(scanf("%d %d",&n,&m)!=EOF)
    {
        memset(du,0,sizeof(du));
        for(i=1;i<=n;i++)g[i].clear();
        for(i=1;i<=m;i++)
        {
            scanf("%d %d",&u,&v);
            g[u].push_back(v);
            du[v]++;
        }
        topsort();
        for(i=1;i<=n;i++)
        {
            if(i!=n)
                printf("%d ",val[i]);
            else
                printf("%d\n",val[i]);
        }
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: