主题:[讨论]这道题怎么做啊~~~
Description
ACMer在ZQU已经有好几年的历史了,最近,他们想成立一个协会,叫ZQU_ICPC协会。我们都知道,在ZQU成立一个协会是需要很多手续的,而且还有一个人数上的条件,即必须满足一定的人数才可以得到学校的批准。
所以,现有的ACMer开始到处宣传,希望能够找到尽量多的人进入协会。
现在给出同学们的关系以及最开始的ACMer的号码。
请问他们的人数足够满足条件吗?
Input
输入有多个测试用例。
每个测试用例的第一行是三个数字n,m和num,n表示一共有多少个人,m表示有多少同学之间是有关系的,num表示成立协会的最少人数。( 1 < n <100 ,m<200 , num <= n )
接下来有m行,每行两个数字 a b,表示a和b有关系,只要其中一个加入ZQU_ICPC协会,那么另外一个也会加入到ACMer的行列。
接下来一行是一个数字k,表示最开始有k个ACMer,接下来一行有k个数字(0 <= ki < n)表示最初的ACMer们的编号。
Output
对于每个测试用例,如果满足人数上的条件,输出"YES",否则输出"SORRY"
Sample Input
10 5 5
1 2
0 2
6 7
4 2
3 1
1 // 最开始有多少个人 接下来是每个人的编号
4
Sample Output
YES
//-----------------------
这是我的代码 但是超时了 有没有更好的方法?
[code=c]
#include <stdio.h>
#define size 200
int parents[size];
int deep[size];
int s[100];
void INIT(int x)
{
parents[x] = x;
deep[x] = 0;
}
int Find(int x)
{
int par,tem;
par = x;
while(parents[par]!=par)
par = parents[par];
while (x!=par)
{
tem = parents[x];
parents[x] = par;
x = tem;
}
return par;
}
void Union(int a,int b)
{
int t1 = Find(a);
int t2 = Find(b);
if(deep[t1]<deep[t2])
parents[t1] = t2;
else
parents[t2] = t1;
if(deep[t1] == deep[t2])
deep[t1]++;
}
int Search(int t,int j)
{
int i;
for(i=0;i<j;i++)
{
if(t == s[i])
{
return 1;
}
}
return 0;
}
int main()
{
int i,k,j,ii,jj;
int peo,known,needs,n,t,sum;
int a,b;
while(scanf("%d%d%d",&peo,&known,&needs))
{
for(i=0;i<peo;i++)
INIT(i);
while(known--)
{
scanf("%d%d",&a,&b);
if(Find(a)!=Find(b))
Union(a,b);
}
sum=0;
j=0;
scanf("%d",&n);
for(k=0;k<n;k++)
{
scanf("%d",&t);
t=Find(t);
if(Search(t,j))
{
continue;
}
s[j]=t;j++;
for(i=0;i<peo;i++)
{
if(Find(i) == t)
{
sum++;
}
}
}
if(sum >= needs)
{
printf("YES\n");
}
else
{
printf("SORRY\n");
}
}
return 0;
}[/code]
ACMer在ZQU已经有好几年的历史了,最近,他们想成立一个协会,叫ZQU_ICPC协会。我们都知道,在ZQU成立一个协会是需要很多手续的,而且还有一个人数上的条件,即必须满足一定的人数才可以得到学校的批准。
所以,现有的ACMer开始到处宣传,希望能够找到尽量多的人进入协会。
现在给出同学们的关系以及最开始的ACMer的号码。
请问他们的人数足够满足条件吗?
Input
输入有多个测试用例。
每个测试用例的第一行是三个数字n,m和num,n表示一共有多少个人,m表示有多少同学之间是有关系的,num表示成立协会的最少人数。( 1 < n <100 ,m<200 , num <= n )
接下来有m行,每行两个数字 a b,表示a和b有关系,只要其中一个加入ZQU_ICPC协会,那么另外一个也会加入到ACMer的行列。
接下来一行是一个数字k,表示最开始有k个ACMer,接下来一行有k个数字(0 <= ki < n)表示最初的ACMer们的编号。
Output
对于每个测试用例,如果满足人数上的条件,输出"YES",否则输出"SORRY"
Sample Input
10 5 5
1 2
0 2
6 7
4 2
3 1
1 // 最开始有多少个人 接下来是每个人的编号
4
Sample Output
YES
//-----------------------
这是我的代码 但是超时了 有没有更好的方法?
[code=c]
#include <stdio.h>
#define size 200
int parents[size];
int deep[size];
int s[100];
void INIT(int x)
{
parents[x] = x;
deep[x] = 0;
}
int Find(int x)
{
int par,tem;
par = x;
while(parents[par]!=par)
par = parents[par];
while (x!=par)
{
tem = parents[x];
parents[x] = par;
x = tem;
}
return par;
}
void Union(int a,int b)
{
int t1 = Find(a);
int t2 = Find(b);
if(deep[t1]<deep[t2])
parents[t1] = t2;
else
parents[t2] = t1;
if(deep[t1] == deep[t2])
deep[t1]++;
}
int Search(int t,int j)
{
int i;
for(i=0;i<j;i++)
{
if(t == s[i])
{
return 1;
}
}
return 0;
}
int main()
{
int i,k,j,ii,jj;
int peo,known,needs,n,t,sum;
int a,b;
while(scanf("%d%d%d",&peo,&known,&needs))
{
for(i=0;i<peo;i++)
INIT(i);
while(known--)
{
scanf("%d%d",&a,&b);
if(Find(a)!=Find(b))
Union(a,b);
}
sum=0;
j=0;
scanf("%d",&n);
for(k=0;k<n;k++)
{
scanf("%d",&t);
t=Find(t);
if(Search(t,j))
{
continue;
}
s[j]=t;j++;
for(i=0;i<peo;i++)
{
if(Find(i) == t)
{
sum++;
}
}
}
if(sum >= needs)
{
printf("YES\n");
}
else
{
printf("SORRY\n");
}
}
return 0;
}[/code]