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 }

 

posted @ 2012-07-02 19:40  BeatLJ  阅读(311)  评论(0编辑  收藏  举报