COJ1081(集训队分组)

Description

中南大学ACM的暑期集训马上就要开始了,这次集训会将全体N名集训队员(编号分别为1, 2, …, N)按集训选拔赛的排名分成两组,前K名队员分入A组,其余队员分入B组。

但现在助理教练CSGrandeur一不小心把集训选拔赛的排名弄丢了,而之前又没将A组和B组的人员确定出来,于是CSGrandeur打算问一下集训人员他们的名次各是怎样的,以此来确定一下A组的队员。

然而集训队员们都视名次如粪土,只是隐约记得某些人排在了自己的后面,最终反馈到CSGrandeur这里的一共有M条信息,每条信息都可以用一个二元组(x, y) (x!=y)表示,含义为第x名队员记得第y名队员的排名比自己的要靠后。

现在CSGrandeur想知道,根据这M条信息,是否可以确定出A组的队员呢?(默认所有集训队员反映的信息都是符合事实的。)

 

Input

输入包含多组测试数据。

对于每组测试数据,第一行包含三个正整数N (2<=N<=1000)、K (1<=K<=N)、M (1<=M<=10000),含义同上。接下来M行每行有两个正整数x、y (1<=x, y<=N且x!=y),分别描述了M条信息,对于每对x、y,均表示第x名队员记得第y名队员的排名比自己的要靠后。

Output

对于每组测试数据,如果可以确定出A组的队员,输出“YES”(不包括引号),否则输出“NO”(不包括引号)。

Sample Input

3 1 2

1 2

1 3



3 2 2

1 2

1 3

Sample Output

YES

NO

数学模型:给定n个未知数,m组关系,没组关系指出n个未知数中的2个的大小关系,例如A>B,求能否据此确定前k个数的集合?

一开始想到并查集,写了好几次都WA了,最后发现此题中的关系并不是等价关系。后来想到一个类似的题,那题也是给定n个未知数和一些大小关系,要求的是能否确定所有数的大小关系。那题是用拓扑排序做的。用拓扑排序的方法很容易找出一组符合条件的解,关键在于如何判断解的唯一性,如果解是唯一的,那么剩下的n-k个数一定在所选的k个数的后面,也就是从这所选的k个数(图中表示为结点)中任意一个出发,可以遍历到剩下的n-k个数。问题也就解决了。

View Code
 1 #include <stdio.h>

 2 #include <string.h>

 3 #include <vector>

 4 #define N 1001

 5 using namespace std;

 6 vector<int> g[N];

 7 int n,k,m,cnt,d[N],a[N],vis[N],flag[N];

 8 void dfs(int u)

 9 {

10   int i,v;

11   if(flag[u]==0 && vis[u]==0) cnt++;

12   vis[u]=1;

13   for(i=0;i<g[u].size();i++)

14   {

15     v=g[u][i];

16     if(!vis[v])  dfs(v);

17   }

18 }

19 int main()

20 {

21   int i,u,v;

22   while(~scanf("%d%d%d",&n,&k,&m))

23   {

24     for(i=1;i<=n;i++)

25     {

26       g[i].clear();

27       d[i]=0;

28     }

29     for(i=0;i<m;i++)

30     {

31       scanf("%d%d",&u,&v);

32       g[u].push_back(v);

33       d[v]++;

34     }

35     memset(flag,0,sizeof(flag));

36     cnt=0;

37     while(cnt<k)

38     {

39       for(u=1;u<=n && d[u];u++);

40       d[u]--;

41       a[cnt++]=u;

42       flag[u]=1;

43       for(i=0;i<g[u].size();i++)

44       {

45         v=g[u][i];

46         d[v]--;

47       }

48     }

49     for(i=0;i<k;i++)

50     {

51       u=a[i];

52       cnt=0;

53       memset(vis,0,sizeof(vis));

54       dfs(u);

55       if(cnt!=n-k)  break;

56     }

57     if(i<k) puts("NO");

58     else  puts("YES");

59   }

60   return 0;

61 }

 

你可能感兴趣的:(分组)