集训队分组
2015-06-22 00:35
253 查看
但现在助理教练CSGrandeur一不小心把集训选拔赛的排名弄丢了,而之前又没将A组和B组的人员确定出来,于是CSGrandeur打算问一下集训人员他们的名次各是怎样的,以此来确定一下A组的队员。
然而集训队员们都视名次如粪土,只是隐约记得某些人排在了自己的后面,最终反馈到CSGrandeur这里的一共有M条信息,每条信息都可以用一个二元组(x, y) (x!=y)表示,含义为第x名队员记得第y名队员的排名比自己的要靠后。
现在CSGrandeur想知道,根据这M条信息,是否可以确定出A组的队员呢?(默认所有集训队员反映的信息都是符合事实的。)
对于每组测试数据,第一行包含三个正整数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名队员的排名比自己的要靠后。
建有向图,对每个结点bfs一遍,找出从它出发可以到达多少个结点,如果有n-k个结点在它之后,那它就是前k个了;
邻接矩阵会超时,要使用邻接表;
# include <iostream>
# include <cstdio>
# include <cstring>
# include <vector>
# define N 1005
using namespace std;
vector<int> g
;
char vis
;
int bfs(int u)
{
int i, cx, nx, ret;
int Q
, front, rear;
Q[1] = u;
memset(vis, 0, sizeof(vis));
vis[u] = 1;
front = 1;
rear = 2;
ret = 0;
while (front < rear)
{
cx = Q[front++];
for (i = 0; i < g[cx].size(); ++i)
{
nx = g[cx][i];
if (!vis[nx])
{
Q[rear++] = nx;
vis[nx] = 1;
++ret;
}
}
}
return ret;
}
int main()
{
int i, n, u, v, k, m, cnt;
while (~scanf("%d%d%d", &n, &k, &m))
{
for (i = 1; i <= n; ++i) g[i].clear();
for (i = 0; i < m; ++i)
{
scanf("%d%d", &u, &v);
g[u].push_back(v);
}
cnt = 0;
for(i = 1; i <= n; ++i)
{
if (bfs(i) >= n-k) ++cnt;
if (cnt >= k) break;
}
puts(cnt>=k ? "YES":"NO");
}
return 0;
}
2.。。。。
/*Accepted 880 kb 268 ms C++/ 1671 B 2012-07-29 17:08:30*/
#include<cstdio>
#include<cstring>
#include<cstdlib>
const int MAXN = 1 << 10;
const int MAXM = 10010;
int N, K, M, first[MAXN], e, next[MAXM], v[MAXM];
int topo[MAXN], cnt, vis[MAXN];
void addedge(int x, int y)
{
v[e] = y;
next[e] = first[x], first[x] = e ++;
}
void ReadGraph()
{
int i, x, y;
memset(first, -1, sizeof first);
e = 0;
for(i = 0; i < M; i ++)
{
scanf("%d%d", &x, &y);
addedge(x, y);
}
}
void dfs(int cur)
{
int i;
vis[cur] = 1;
for(i = first[cur]; i != -1; i = next[i])
if(!vis[v[i]])
dfs(v[i]);
topo[cnt --] = cur;
}
void toposort()
{
int i;
cnt = N;
memset(vis, 0, sizeof vis);
for(i = 1; i <= N; i ++)
if(!vis[i])
dfs(i);
}
void Search(int cur)
{
int i;
vis[cur] = 1;
for(i = first[cur]; i != -1; i = next[i])
if(!vis[v[i]])
Search(v[i]);
}
bool judge()
{
int i, j;
for(i = 1; i <= K; i ++)
{
memset(vis, 0, sizeof vis);
Search(topo[i]);
for(j = K + 1; j <= N; j ++)
if(!vis[topo[j]])
return false;
}
return true;
}
int main()
{
while(scanf("%d%d%d", &N, &K, &M) == 3)
{
ReadGraph();
toposort();
bool ok = judge();
if(ok)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
数学模型:给定n个未知数,m组关系,没组关系指出n个未知数中的2个的大小关系,例如A>B,求能否据此确定前k个数的集合?
一开始想到并查集,写了好几次都WA了,最后发现此题中的关系并不是等价关系。后来想到一个类似的题,那题也是给定n个未知数和一些大小关系,要求的是能否确定所有数的大小关系。那题是用拓扑排序做的。用拓扑排序的方法很容易找出一组符合条件的解,关键在于如何判断解的唯一性,如果解是唯一的,那么剩下的n-k个数一定在所选的k个数的后面,也就是从这所选的k个数(图中表示为结点)中任意一个出发,可以遍历到剩下的n-k个数。问题也就解决了。
#include <stdio.h>
#include <string.h>
#include <vector>
#define N 1001
using namespace std;
vector<int> g
;
int n,k,m,cnt,d
,a
,vis
,flag
;
void dfs(int u)
{
int i,v;
if(flag[u]==0 && vis[u]==0) cnt++;
vis[u]=1;
for(i=0;i<g[u].size();i++)
{
v=g[u][i];
if(!vis[v]) dfs(v);
}
}
int main()
{
int i,u,v;
while(~scanf("%d%d%d",&n,&k,&m))
{
for(i=1;i<=n;i++)
{
g[i].clear();
d[i]=0;
}
for(i=0;i<m;i++)
{
scanf("%d%d",&u,&v);
g[u].push_back(v);
d[v]++;
}
memset(flag,0,sizeof(flag));
cnt=0;
while(cnt<k)
{
for(u=1;u<=n && d[u];u++);
d[u]--;
a[cnt++]=u;
flag[u]=1;
for(i=0;i<g[u].size();i++)
{
v=g[u][i];
d[v]--;
}
}
for(i=0;i<k;i++)
{
u=a[i];
cnt=0;
memset(vis,0,sizeof(vis));
dfs(u);
if(cnt!=n-k) break;
}
if(i<k) puts("NO");
else puts("YES");
}
return 0;
}
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 3Sample Output
YES NO建有向图,对每个结点bfs一遍,找出从它出发可以到达多少个结点,如果有n-k个结点在它之后,那它就是前k个了;
邻接矩阵会超时,要使用邻接表;
# include <iostream>
# include <cstdio>
# include <cstring>
# include <vector>
# define N 1005
using namespace std;
vector<int> g
;
char vis
;
int bfs(int u)
{
int i, cx, nx, ret;
int Q
, front, rear;
Q[1] = u;
memset(vis, 0, sizeof(vis));
vis[u] = 1;
front = 1;
rear = 2;
ret = 0;
while (front < rear)
{
cx = Q[front++];
for (i = 0; i < g[cx].size(); ++i)
{
nx = g[cx][i];
if (!vis[nx])
{
Q[rear++] = nx;
vis[nx] = 1;
++ret;
}
}
}
return ret;
}
int main()
{
int i, n, u, v, k, m, cnt;
while (~scanf("%d%d%d", &n, &k, &m))
{
for (i = 1; i <= n; ++i) g[i].clear();
for (i = 0; i < m; ++i)
{
scanf("%d%d", &u, &v);
g[u].push_back(v);
}
cnt = 0;
for(i = 1; i <= n; ++i)
{
if (bfs(i) >= n-k) ++cnt;
if (cnt >= k) break;
}
puts(cnt>=k ? "YES":"NO");
}
return 0;
}
2.。。。。
/*Accepted 880 kb 268 ms C++/ 1671 B 2012-07-29 17:08:30*/
#include<cstdio>
#include<cstring>
#include<cstdlib>
const int MAXN = 1 << 10;
const int MAXM = 10010;
int N, K, M, first[MAXN], e, next[MAXM], v[MAXM];
int topo[MAXN], cnt, vis[MAXN];
void addedge(int x, int y)
{
v[e] = y;
next[e] = first[x], first[x] = e ++;
}
void ReadGraph()
{
int i, x, y;
memset(first, -1, sizeof first);
e = 0;
for(i = 0; i < M; i ++)
{
scanf("%d%d", &x, &y);
addedge(x, y);
}
}
void dfs(int cur)
{
int i;
vis[cur] = 1;
for(i = first[cur]; i != -1; i = next[i])
if(!vis[v[i]])
dfs(v[i]);
topo[cnt --] = cur;
}
void toposort()
{
int i;
cnt = N;
memset(vis, 0, sizeof vis);
for(i = 1; i <= N; i ++)
if(!vis[i])
dfs(i);
}
void Search(int cur)
{
int i;
vis[cur] = 1;
for(i = first[cur]; i != -1; i = next[i])
if(!vis[v[i]])
Search(v[i]);
}
bool judge()
{
int i, j;
for(i = 1; i <= K; i ++)
{
memset(vis, 0, sizeof vis);
Search(topo[i]);
for(j = K + 1; j <= N; j ++)
if(!vis[topo[j]])
return false;
}
return true;
}
int main()
{
while(scanf("%d%d%d", &N, &K, &M) == 3)
{
ReadGraph();
toposort();
bool ok = judge();
if(ok)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
数学模型:给定n个未知数,m组关系,没组关系指出n个未知数中的2个的大小关系,例如A>B,求能否据此确定前k个数的集合?
一开始想到并查集,写了好几次都WA了,最后发现此题中的关系并不是等价关系。后来想到一个类似的题,那题也是给定n个未知数和一些大小关系,要求的是能否确定所有数的大小关系。那题是用拓扑排序做的。用拓扑排序的方法很容易找出一组符合条件的解,关键在于如何判断解的唯一性,如果解是唯一的,那么剩下的n-k个数一定在所选的k个数的后面,也就是从这所选的k个数(图中表示为结点)中任意一个出发,可以遍历到剩下的n-k个数。问题也就解决了。
#include <stdio.h>
#include <string.h>
#include <vector>
#define N 1001
using namespace std;
vector<int> g
;
int n,k,m,cnt,d
,a
,vis
,flag
;
void dfs(int u)
{
int i,v;
if(flag[u]==0 && vis[u]==0) cnt++;
vis[u]=1;
for(i=0;i<g[u].size();i++)
{
v=g[u][i];
if(!vis[v]) dfs(v);
}
}
int main()
{
int i,u,v;
while(~scanf("%d%d%d",&n,&k,&m))
{
for(i=1;i<=n;i++)
{
g[i].clear();
d[i]=0;
}
for(i=0;i<m;i++)
{
scanf("%d%d",&u,&v);
g[u].push_back(v);
d[v]++;
}
memset(flag,0,sizeof(flag));
cnt=0;
while(cnt<k)
{
for(u=1;u<=n && d[u];u++);
d[u]--;
a[cnt++]=u;
flag[u]=1;
for(i=0;i<g[u].size();i++)
{
v=g[u][i];
d[v]--;
}
}
for(i=0;i<k;i++)
{
u=a[i];
cnt=0;
memset(vis,0,sizeof(vis));
dfs(u);
if(cnt!=n-k) break;
}
if(i<k) puts("NO");
else puts("YES");
}
return 0;
}
相关文章推荐
- 【吾日三省吾身】2015.6.21-涅槃行动第三十四天
- windows7系统 Internet 信息服务(IIS)管理器 默认网站 右键 没有属性这一项怎么办?
- leetcode(2)add two numbers
- Unicode字符集下CString与char *转换
- Oracle dbms_random随机数包详解
- 随笔
- python传值机制
- python传值机制
- cookie、session、localStorage、sessionStorage
- HOOK API (一)——HOOK基础+一个鼠标钩子实例
- Concurrency vs. Parallelism
- poj 3984 迷宫问题
- xstream 对XML提供特殊解析
- 2015四川省赛 scu oj 4438 Censor
- 2015四川省赛 scu oj 4445 Right turn
- raspberry pi2 andrid
- U盘安装UEFI Debian 8.1 + Windows 8.1双系统
- SSH无需密码密钥登录
- ios网络之配置apache服务器
- 换主页轮播的主题图片(3、保存添加)---轻开电子商务系统(企业入门级B2C网站)