NKUACM最近要举行足球赛,作为此次赛事的负责人,Lee要对报名人员进行分队。分队要遵循如下原则:
- 一个人不能加入多支队伍;
- 不认识的人不能分在同一队;
- 如果a和b认识,b和c认识,那么认为a和c也认识;
- 每支队伍上限8人,下限5人;
- 尽量使队伍满员。
由于参赛人数很多,Lee表示无能为力,所以请你帮助Lee编程解决比赛有多少队伍。
Input
第一行输入两个整数,n和m,n(1<=n<=300000)代表报名人数,m(1<=m<=500000)代表关系数。接下来m行每行两个整数a(1<=a<=n)和b(1<=b<=n)表示a和b认识。
Output
输出一行,包含一个整数,表示队伍数量。
Sample Input
11 10
1 2
2 3
2 6
3 4
4 5
5 6
7 9
9 11
11 8
8 10
Sample Output
2
//使用邻接表存储图
//深度优先遍历的典型示例
#include<stdio.h>
#include<stdlib.h>
#define status int
#define YES 0
#define NO 1
#define OK 0
#define ERROR 1
#define MAX_VEX 300
int visited[MAX_VEX];//标示是否被访问过
typedef struct ArcNode//边界点的结构类型
{
int adjvex;
struct ArcNode *next;
}ArcNode;
typedef struct VexNode//临界表的表头结构
{
int vex;
ArcNode *link;
}VexNode,AdjList[MAX_VEX];
typedef struct Graph//图的结构类型
{
AdjList list;
int vexnum,arcnum;
}Graph;
status creatGraph(Graph &G);//创建邻接表
int DFSTravers(Graph G);//深度优先遍历,作必要的处理,队伍个数的确定,返回队伍的个数
int DFS(Graph G,int v);//深度优先遍历返回此次遍历强连通分量的结点个数
int main()
{
Graph G;
if(creatGraph(G)==OK)
printf("%d\n",DFSTravers(G));
system("pause");
return 0;
}
status creatGraph(Graph &G)
{
int i,j,k;
ArcNode *p,*q;
p=q=NULL;
scanf("%d %d",&G.vexnum,&G.arcnum);
if(G.vexnum<1||G.vexnum>300000||G.arcnum<1||G.arcnum>500000)
{
printf("数字超出范围");
return ERROR;
}
for(i=0;i<=G.vexnum;i++)
{
G.list[i].vex=i;
G.list[i].link=NULL;
}
for(k=0;k<G.arcnum;k++)
{
p=q=NULL;
scanf("%d %d",&i,&j);
if(i<1||i>G.vexnum||j<1||j>G.vexnum)
{
printf("数字超出范围");
return ERROR;
}
p=G.list[i].link;
while(p!=NULL)
{
q=p;//q此时被保存为p的前驱
p=p->next;
}
p=q;
q=(ArcNode *)malloc(sizeof(ArcNode));
q->adjvex=j;
q->next=NULL;
if(p!=NULL)
p->next=q;
if(G.list[i].link==NULL)
G.list[i].link=q;
}
return OK;
}
int DFSTravers(Graph G)
{
int v,w;
int sum_people;
int sum_team;
sum_people=0;
sum_team=0;
for(v=0;v<=G.vexnum;v++)
visited[v]=NO;
for(v=1;v<=G.vexnum;v++)//编号从1开始
{
sum_people=0;
if(visited[v]==NO)
sum_people=DFS(G,v);
if(sum_people>=5)//下限为5
{
sum_team+=sum_people/8;
if(sum_people%8>=5)
sum_team++;
}
}
return sum_team;
}
int DFS(Graph G,int v)
{
int count;//作为返回值,记录此次遍历强连通分量的结点个数
ArcNode *p;//作为临时变量,遍历以v为头的所有链接点
count=0;
visited[v]=YES;
count++;
for(p=G.list[v].link;p!=NULL;p=p->next)
if(visited[p->adjvex]==NO)
{
count+=DFS(G,p->adjvex);
}
return count;
}