题意:
有一群人,给出一些朋友关系,如果两个人有不少于k个共同朋友,那么他们也能成为朋友,问有多少人能成为新朋友
解题思路:
设num[i][j]记录i和j之间有多少个共同朋友,我们去枚举每个人,将每个人的所有朋友xi,num[x[i]][x[i+1]]++,最后去判断有多少个num[i][j]>=k,用队列去记录,让他们成为朋友,然后再把队列里记录的这些新朋友相关的num[i][j]++,再去判断是否有新朋友,加入到队列中,知道队列为空,答案就是队列的大小。
ps:to myself,队列记录的是边,边的数量是点的数量的平方,所以数组相应要开大。忘了这点看了一小时代码也没找出错。。
代码:
#include <bits/stdc++.h>
using namespace std;
int fri[105][105];
struct p
{
int x;
int y;
}que[10523];
int x[105];
int y[105];
int num[105][105];
int top;
int book[105][105];
int main()
{
int t;
cin>>t;
while(t--)
{
int n, m, q;
top=0;
scanf("%d %d %d", &n, &m, &q);
int a, b, i, j;
memset(fri, 0, sizeof(fri));
memset(book, 0, sizeof(book));
memset(num, 0, sizeof(num));
for(i=0; i<m; i++)
{
scanf("%d %d", &a, &b);
x[i]=a;
y[i]=b;
fri[a][b]=1;
fri[b][a]=1;
}
int k;
for(i=0; i<n; i++)
{
for(j=0; j<n; j++)
{
if(fri[i][j])
{
for(k=j+1; k<n; k++)
{
if(fri[i][k])num[j][k]++;
}
}
}
}
int head, tail;
head=tail=0;
for(i=0; i<n; i++)
{
for(j=i+1; j<n; j++)
{
if(num[i][j]>=q && fri[i][j]==0)que[tail].x=i, que[tail++].y=j, book[i][j]=book[j][i]=1, fri[j][i]=fri[i][j]=1;
}
}
// printf("%d\n", tail);
while(head<tail)
{
int a, b;
a=que[head].x;
b=que[head].y;
// printf("%d %d\n", a, b);
for(i=0; i<n; i++)
{
if(i!=a && fri[a][i])
{
//printf("%d %d\n", i, a);
k=min(b,i);
j=max(b,i);
num[k][j]++;
//if(k!=j && num[k][j]>=q && book[k][j]==0 && fri[k][j]==0)fri[k][j]=1, fri[j][k]=1, que[tail].x=k, que[tail++].y=j, book[k][j]=book[j][k]=1;
}
if(i!=b && fri[b][i])
{
//printf("%d %d\n", i, b);
k=min(a,i);
j=max(a,i);
num[k][j]++;
//if(k!=j && num[k][j]>=q && book[k][j]==0 && fri[k][j]==0)fri[k][j]=fri[j][k]=1,que[tail].x=k, que[tail++].y=j, book[k][j]=book[j][k]=1;
}
}
for(i=0; i<n; i++)
{
for(j=i+1; j<n; j++)
{
if(num[i][j]>=q && fri[i][j]==0)que[tail].x=i, que[tail++].y=j, book[i][j]=book[j][i]=1, fri[j][i]=fri[i][j]=1;
}
}
head++;
}
printf("%d\n", tail);
}
}