拓扑排序

拓扑排序:由某个集合上的一个偏序得到该集合上的一个全序的操作。

拓扑排序操作过程:首先选择一个无前驱的顶点(即入度为0的顶点,图中至少应该有一个这样的顶点,否则肯定存在回路),然后从图中移去该顶点以及由其发出的所有有向边,如果图中还存在无前驱的顶点,则重复上述操作,直到操作无法进行。如果图不为空,说明图中存在回路,无法进行拓扑排序;否则移出的顶点的顺序就是对该图的一个拓扑排序。
例题1:hdu 1285题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1285,简单的拓扑排序问题,代码:

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int MAX=505;
#define CLR(arr,val) memset(arr,val,sizeof(arr))
int n,m,Indgree[MAX],map[MAX][MAX],top[MAX];
bool visited[MAX];
void Init()
{   CLR(map,0);
    CLR(Indgree,0);
}
void TopSort()
{   int num=1;
    CLR(visited,false);
    for(int i=1;i<=n;i++)
    {   for(int j=1;j<=n;j++)
            if(!Indgree[j]&&!visited[j])//找出度数为0的点,且没有被访问 
            {   visited[j]=true;
                top[num++]=j;
                break;//这里一定要加break语句,可能题目中入度为0的点不只一个
            }
        for(int k=1;k<=n;k++)
            if(map[top[num-1]][k])
            {   map[top[num-1]][k]=0; //移除与该点相连的边
                Indgree[k]--;
            }
    }
} 
int main()
{   int u,v;
    while(cin>>n>>m)
    {   Init();
        for(int i=1;i<=m;i++)
        {   cin>>u>>v;
            if(!map[u][v])
            {   map[u][v]=1;
                Indgree[v]++;
            }   
        }
        TopSort();
        for(int i=1;i<=n;i++)
           cout<<(i==1?"":" ")<<top[i];
        cout<<endl;
    }
    return 0;
}

涉及到拓扑排序的题目有:HDU 3342,2647,POJ 1094,2367,3272,3687等等

其中HDU 3342是判断能不能进行拓扑排序,也就是说能不能形成环,只要在上面的例子中看num==n就输出"YES",否则输出"NO".

nyist 349,题目链接:NYOJ 349(Sorting It All Out),要分析的情况很多,不会做~~贴个代码,慢慢的看~~~奋斗

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int MAX=30;
#define CLR(arr,val) memset(arr,val,sizeof(arr))
int n,m,temp[MAX],Indgree[MAX],map[MAX][MAX],top[MAX];
void Init()
{   CLR(Indgree,0);
	CLR(map,0);
}
int Topsort()
{   int num=0,flag=1,sum;
    for(int i=0;i<n;i++)
		temp[i]=Indgree[i];
	for(int k=0;k<n;k++)
    {   sum=0;
		for(int j=0;j<n;j++)
		{   if(!temp[j])
			{   top[num++]=j;
				sum++;
			}
		}
		if(sum==0) return -1;
		if(sum>1) flag=0;
		temp[top[num-1]]--;
		for(int j=0;j<n;j++)
			if(map[top[num-1]][j]) temp[j]--;
	}
	if(flag)  return 1;
    return 0;
}
int main()
{   while(scanf("%d%d",&n,&m)&&n||m)
	{   Init();
	    int flag=1;
    	for(int i=0;i<m;i++)
        {   char s[3];
            scanf("%s",s);
            if(!map[s[0]-'A'][s[2]-'A']) 
		    {   map[s[0]-'A'][s[2]-'A']=1;
                Indgree[s[2]-'A']++; 
            }
            if(flag)
	     	{   if(Topsort()==1)
			    {   printf("Sorted sequence determined after %d relations: ",i+1);
			      	for(int j=0;j<n;j++)
					    printf("%c",top[j]+'A');
				    printf(".\n");
				    flag=0;
		     	}
			    if(Topsort()==-1)
			    {   printf("Inconsistency found after %d relations.\n",i+1);
				    flag=0;
			    }
		    }
       }
	   if(flag) printf("Sorted sequence cannot be determined.\n");
	}
	return 0;
}

这个代码放在POJ的1094上会WA~有时候真的没有搞懂~~~超不爽!头都弄晕了~
~~~

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int MAX=1000;
#define CLR(arr,val) memset(arr,val,sizeof(arr))
int Indegree[MAX],map[MAX][MAX],top[MAX];
int n,m,visit[MAX];
void Init()
{   CLR(map,0);
    CLR(Indegree,0);
}
int Topsort()
{   int num=0;
    CLR(visit,0);
    for(int i=1;i<=n;i++)
    {   for(int j=1;j<=n;j++)
            if(!Indegree[j]&&!visit[j])
            {   visit[j]=1;
                top[num++]=j; //找出入度为0的点
                break;
            }
        for(int j=1;j<=n;j++)
            if(map[top[num-1]][j])
            {   map[top[num-1]][j]=0;
                Indegree[j]--;
            }
    }
    if(num==n) return 1;
    return 0;
}
int main()
{   int u,v,Case;
    scanf("%d",&Case);
    while(Case--)
    {   scanf("%d%d",&n,&m);
        Init();
        for(int i=0;i<m;i++)
        {   scanf("%d%d",&u,&v); //要安装u必须先安装v,u为入度
            map[v][u]=1;
            Indegree[u]++; 
        }
        if(Topsort())
        {   for(int i=0;i<n-1;i++)
                printf("%d ",top[i]);
            printf("%d\n",top[n-1]);    
        }
        else printf("-1\n"); 
         
    }
    system("pause");
    return 0;
}
 

你可能感兴趣的:(c,ini)