• 暑假集训之专题----拓扑排序题解


    第一单:

    Problem A

    Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other)
    Total Submission(s) : 26   Accepted Submission(s) : 5
    Problem Description
    ACM-DIY is a large QQ group where many excellent acmers get together. It is so harmonious that just like a big family. Every day,many "holy cows" like HH, hh, AC, ZT, lcc, BF, Qinz and so on chat on-line to exchange their ideas. When someone has questions, many warm-hearted cows like Lost will come to help. Then the one being helped will call Lost "master", and Lost will have a nice "prentice". By and by, there are many pairs of "master and prentice". But then problem occurs: there are too many masters and too many prentices, how can we know whether it is legal or not? We all know a master can have many prentices and a prentice may have a lot of masters too, it's legal. Nevertheless,some cows are not so honest, they hold illegal relationship. Take HH and 3xian for instant, HH is 3xian's master and, at the same time, 3xian is HH's master,which is quite illegal! To avoid this,please help us to judge whether their relationship is legal or not. Please note that the "master and prentice" relation is transitive. It means that if A is B's master ans B is C's master, then A is C's master.
     
    Input
    The input consists of several test cases. For each case, the first line contains two integers, N (members to be tested) and M (relationships to be tested)(2 <= N, M <= 100). Then M lines follow, each contains a pair of (x, y) which means x is y's master and y is x's prentice. The input is terminated by N = 0. TO MAKE IT SIMPLE, we give every one a number (0, 1, 2,..., N-1). We use their numbers instead of their names.
     
    Output
    For each test case, print in one line the judgement of the messy relationship. If it is legal, output "YES", otherwise "NO".
     
    Sample Input
    3 2 0 1 1 2 2 2 0 1 1 0 0 0
     
    Sample Output
    YES
    NO
    裸裸的拓扑排序,只需要判断是否成环即可.......
     
     代码:
     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<stdlib.h>
     4 const int maxn=105;
     5 int map[maxn][maxn];
     6 int indegree[maxn];
     7 int n,m;
     8 int main()
     9 {
    10     int x,y;
    11     while(scanf("%d%d",&n,&m)!=EOF&&n+m!=0)
    12     {
    13      memset(map,0,sizeof(map));
    14      memset(indegree,0,sizeof(indegree));
    15       while(m--)
    16       {
    17         scanf("%d%d",&x,&y);
    18         x++;
    19         y++;
    20         if(!map[x][y])
    21         {
    22          map[x][y]=1;
    23          indegree[y]++;
    24         }
    25       }
    26       int j;
    27       bool flag=1;
    28       for(int i=1;i<=n;i++)
    29       {
    30           for(j=1;j<=n;j++)
    31           {
    32               if(indegree[j]==0)
    33               {
    34                 indegree[j]--;
    35                 for(int k=1;k<=n;k++)
    36                 {
    37                   if(map[j][k])
    38                     indegree[k]--;
    39                 }
    40                 break ;
    41               }
    42           }
    43           if(j>n){
    44             flag=0;
    45             break;
    46           }
    47       }
    48       printf(flag==0?"NO
    ":"YES
    ");
    49     }
    50  return 0;
    51 }
    View Code

    Problem A

    Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other)
    Total Submission(s) : 25   Accepted Submission(s) : 8
    Problem Description
    有N个比赛队(1<=N<=500),编号依次为1,2,3,。。。。,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得每个队的比赛成绩,只知道每场比赛的结果,即P1赢P2,用P1,P2表示,排名时P1在P2之前。现在请你编程序确定排名。
     
    Input
    输入有若干组,每组中的第一行为二个数N(1<=N<=500),M;其中N表示队伍的个数,M表示接着有M行的输入数据。接下来的M行数据中,每行也有两个整数P1,P2表示即P1队赢了P2队。
     
    Output
    给出一个符合要求的排名。输出时队伍号之间有空格,最后一名后面没有空格。 其他说明:符合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前;输入数据保证是正确的,即输入数据确保一定能有一个符合要求的排名。
     
    Sample Input
    4 3 1 2 2 3 4 3
     
    Sample Output
    1 2 4 3
    基础题
    代码:
     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<stdlib.h>
     4 #define maxn 505
     5 bool map[maxn][maxn];
     6 int indegree[maxn],tp[maxn],n,m;
     7 void tuopu_sort()
     8 {
     9     memset(tp,0,sizeof(tp)); //拓扑排序数组清空
    10     int i,j,k=0,ll;
    11     for(i=1;i<=n;i++)
    12     {
    13         for(j=1;j<=n;j++)
    14         {
    15          /*每次取出入读位0的数*/
    16             if(indegree[j]==0)
    17             {
    18                 indegree[j]=-1;  //让他等于-1;表示舍弃掉这个数
    19                 tp[k++]=j;  //放到拓扑序列中 
    20                 /*进行一次循环,去掉所有这个数指向的数的一个度*/
    21                 for(ll=1;ll<=n;ll++)
    22                 {
    23                     if(map[j][ll])  //j-->LL 表示成为map[j][ll]
    24                     {
    25                         indegree[ll]--;  //减少一个
    26                     }
    27                 }
    28                 break;  // 终止,然后进行下次的查找
    29             }
    30         }
    31         if(j>n)
    32         {
    33             //这表示构成了一个环
    34             return ;  //之间结束即可,但是在其他的题中,不能这样...
    35         }
    36     }
    37 }
    38 int main()
    39 {
    40     int i=0,fx,ty;//  fx--->from x to y
    41     while(scanf("%d%d",&n,&m)!=EOF)
    42     {
    43         memset(map,0,sizeof(map));  
    44         memset(indegree,0,sizeof(indegree));
    45         for(i=0;i<m;i++)
    46         {
    47             scanf("%d%d",&fx,&ty);
    48             if(!map[fx][ty])      //防止数据重复
    49             {
    50               map[fx][ty]=true;  
    51               indegree[ty]++;     //入度加一
    52             }
    53         }
    54         tuopu_sort();
    55         for(i=0;i<n-1;i++)
    56         {
    57             printf("%d ",tp[i]);
    58         }
    59         printf("%d
    ",tp[i]);
    60     }
    61     return 0;
    62 }
    View Code

    Problem B

    Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other)
    Total Submission(s) : 17   Accepted Submission(s) : 1
    Problem Description
    Dandelion's uncle is a boss of a factory. As the spring festival is coming , he wants to distribute rewards to his workers. Now he has a trouble about how to distribute the rewards. The workers will compare their rewards ,and some one may have demands of the distributing of rewards ,just like a's reward should more than b's.Dandelion's unclue wants to fulfill all the demands, of course ,he wants to use the least money.Every work's reward will be at least 888 , because it's a lucky number.
     
    Input
    One line with two integers n and m ,stands for the number of works and the number of demands .(n<=10000,m<=20000) then m lines ,each line contains two integers a and b ,stands for a's reward should be more than b's.
     
    Output
    For every case ,print the least money dandelion 's uncle needs to distribute .If it's impossible to fulfill all the works' demands ,print -1.
     
    Sample Input
    2 1 1 2 2 2 1 2 2 1
     
    Sample Output
    1777 -1 
    用邻接表取代邻接矩阵(或者用STL取代之)
    代码:
     1  /*@coder 龚细军*/
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cstdlib>
     5 #include<queue>
     6 #include<vector>  //动态的二维数组
     7 #include<iostream>
     8 using namespace std;
     9 const int maxn=10002;
    10 int n,m;
    11 int cnt[maxn],outd[maxn];
    12 vector< vector<int> >map(maxn);
    13 void tp_sort(int tol)
    14 {
    15  int i;
    16  queue<int>st;
    17  for(i=1;i<=n;i++)
    18  {
    19   if(!outd[i])
    20   {
    21    outd[i]--;
    22    st.push(i);
    23    break;
    24   }
    25  }
    26  //环如何消除
    27  while(!st.empty())
    28  {
    29   int temp=st.front();
    30   vector<int>::iterator it;
    31   for(it=map[temp].begin();it!=map[temp].end();it++)
    32   {
    33    outd[*it]--;
    34    if(cnt[*it]<=cnt[temp])
    35     cnt[*it]=cnt[temp]+1;
    36   }
    37   st.pop();
    38   for(i=1;i<=n;i++)
    39   {
    40    if(!outd[i])
    41    {
    42    outd[i]--;
    43    st.push(i);
    44    break;
    45    }
    46   }
    47  }
    48  for(i=1;i<=n;i++)
    49  {
    50   if(outd[i]!=-1)
    51   {
    52    puts("-1");
    53    return ;
    54   }
    55  }
    56   int ans=0;
    57   for(i=1;i<=n;i++)
    58   {
    59    ans+=cnt[i];
    60   }
    61   if(ans)
    62      printf("%d
    ",n*888+ans);
    63   else
    64    puts("-1");
    65 }
    66 int main()
    67 {
    68  int a,b,i;
    69  while(scanf("%d%d",&n,&m)!=EOF)
    70  {
    71   for(i=1;i<=n;i++) map[i].clear();
    72   memset(outd,0,sizeof(outd));
    73   memset(cnt,0,sizeof(cnt));
    74   i=1;
    75   while(m--)
    76   {
    77       scanf("%d%d",&a,&b);
    78    map[b].push_back(a);
    79    outd[a]++;    /*out++*/
    80   }
    81   tp_sort(i);
    82  }
    83  return 0;
    84 }
    View Code
  • 相关阅读:
    九个令人兴奋的新功能将与Java 9 展示两点
    自学前端开发 新版css时钟效果图
    自学前端,你要的学习资料到了~~~~~~
    Angularjs中ng-repeat与移动端滑动插件iScroll的冲突
    计蒜客学习记录
    明明的随机数
    模板题
    泉州一中复赛模拟
    快速幂模板
    NOIP2013
  • 原文地址:https://www.cnblogs.com/gongxijun/p/3852305.html
Copyright © 2020-2023  润新知