杭电3342Legal or Not (拓扑排序)

来源:互联网 发布:手机淘宝上怎么开网店 编辑:程序博客网 时间:2024/06/08 12:21

拓扑排序简单来说就是把一个图的所有节点排序,使得每一条有向边(u,v)对应的u都排在v的前面。 

拓扑排序最大的用途就是判断一个有向图是否有环,当然判断还有一种方法就是Floyd算法。

如果用邻接表的话拓扑排序的时间复杂度是O(N*E),邻接矩阵是O(N^2),N表示顶点数,E表示边数,Floyd时间复杂度是O(N^3)。

性质
1、 拓扑排序在有向无环图中才能排出有效的序列,否则能判断该有向图有环。
2、如果输入的有向图中的点,不存在入度为0的点,则该有向图存在回路
3、如果存在的入度为0的点大于一个,则该有向图肯定不存在一个可以确定的拓扑序列但并不妨碍拓扑排序 


题意:a是b的老师,b是c的老师,那么a是c的老师。如果a是b的老师,b是c的老师 ,c是a的老师,这样是不合法的。

思路:拓补排序。(既可以排名次)




连通法
#include<stdio.h>-----Floyd时间复杂度是O(N^3)。
#include<string.h>
int f[1000][1000];
int main()
{
    int m,n,i,j,k,h,r,p;
    while(scanf("%d%d",&m,&n),m||n)
    {
        p=0;
        memset(f,0,sizeof(f));
        for(i=0;i<n;i++)
        {
            scanf("%d%d",&k,&h);
            f[k][h]=1;
        }
        for(i=0;i<m;i++)
            for(j=0;j<m;j++)
                for(r=0;r<m;r++)
                    if(f[j][i]==1&&f[i][r]==1)///map[j][i] 便是j 是i 的师傅;
                        f[j][r]=1;
               
                    for(i=0;i<m;i++)
                    {
                        for(j=i+1;j<m;j++)//这里j=i+1,便是只取上半部分进行判断,因为上面的三重循环中为此做了铺垫
                            if(f[i][j]==1&&f[j][i]==1)
                            {
                                p=1;
                                break;
                            }
                            if(p==1)
                                break;
                    }
                    if(p==0)
                        printf("YES\n");
                    else
                        printf("NO\n");
    }
    return 0;
}


方法三

#include<stdio.h>---------邻接矩阵是O(N^2
#include<string.h>
int map[501][501];
int degree[501];
int m,n;
int toposort()
{
 int i,j,r;
 for(i=0;i<n;i++)
  for(j=0;j<n;j++)
   if(map[i][j]==1)
    degree[j]++;
   for(i=0;i<n;i++)
   {
    j=0;
    while(degree[j]!=0)
     j++;
    if(j==n)
    {
     return 0;
    }
    else
    {
      degree[j]--;
        for(r=0;r<n;r++)
     if(map[j][r]==1)
      degree[r]--;
    }
   }
   return 1;
}
int main()
{
 int i,h,k,p;
 while(scanf("%d%d",&n,&m),m||n)
 {
  memset(degree,0,sizeof(degree));
  memset(map,0,sizeof(map));
  for(i=0;i<m;i++)
  {
   scanf("%d%d",&k,&h);
   map[k][h]=1;
  }
   if(toposort())
    printf("YES\n");
   else
    printf("NO\n");
 }
 return 0;
}
   

原创粉丝点击