Legal or Not(拓扑排序)

来源:互联网 发布:什么软件可以看舰娘 编辑:程序博客网 时间:2024/06/03 09:06

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、先开始以为既然是最短路专题,就往知道的上靠了,当然是wa= =原来是要用拓扑排序,来学习一下
2、拓扑排序感觉是先找到一个点,将其放入入度为0的集合中,然后找到所有这个点引出的边,将它们从图中移除,并且获取该边的另一个顶点,如果这个顶点在减去这条边后的入度为0,就将它也放入集合中,然后继续。为了防止重复取,用vis数组记录已经访问过的点,用in数组记录每个点的入度,mp数组记录边,如果联通就是1,移除后变为0。
3、刚才基本照着参考敲了一遍,测试样例也过了,但是提交又是wa,继续测试发现会出现对一个例子有不同的输出,可是明明对那些数组和cnt都进行过初始化了,最终发现我在初始化mp的时候把名字打错了,而用memset它不会报错。 。 。无言以对,不能再手滑了。
4、然后对于代码中的那个break,我认为是它只需要在集合中的点,所以最外面的i是用来控制访问次数,也就是所有点的个数,j就是一个入度为0的点,然后通过k循环去掉所有由j引出的边,这样就会出现符合j条件的点了,在i循环时继续访问那个点。(个人理解= =)

#include <cstdio>#include <algorithm>#include <iostream>#include <cstring>#include <queue>#include <cmath>#define inf 0x3f3f3f3fusing namespace std;int n, m, mp[105][105], in[105], vis[105];int main(){    while((~scanf("%d %d", &n, &m) && n && m)){        int i, j, k, cnt=0;        memset(mp, 0, sizeof(mp));        memset(in, 0, sizeof(in));        memset(vis, 0, sizeof(vis));        for(i=0; i<m; i++){            int x, y;            scanf("%d %d", &x, &y);            if(!mp[x][y])                {mp[x][y]=1;                 in[y]++;}        }        for(i=0; i<n; i++){            for(j=0; j<n; j++){                if(!vis[j] && in[j]==0){                    cnt++;                    vis[j]=1;                    for(k=0; k<n; k++){                        if(mp[j][k])                        {                            mp[j][k]=0;                            in[k]--;                        }                    }                   break;                }            }        }        if(cnt==n)printf("YES\n");            else printf("NO\n");    }    return 0;}
原创粉丝点击