分考场(dfs)

http://lx.lanqiao.cn/problem.page?gpid=T457

问题描述

  n个人参加某项特殊考试。
  为了公平,要求任何两个认识的人不能分在同一个考场。
  求是少需要分几个考场才能满足条件。

输入格式

  第一行,一个整数n(1<n<100),表示参加考试的人数。
  第二行,一个整数m,表示接下来有m行数据
  以下m行每行的格式为:两个整数a,b,用空格分开 (1<=a,b<=n) 表示第a个人与第b个人认识。

输出格式

  一行一个整数,表示最少分几个考场。

样例输入

5
8
1 2
1 3
1 4
2 3
2 4
2 5
3 4
4 5

样例输出

4

样例输入

5
10
1 2
1 3
1 4
1 5
2 3
2 4
2 5
3 4
3 5
4 5

样例输出

5

思路分析:开始是这样想的。。强连通分量来做。感觉思路可以,还未尝试。大概思路就是构图后找强连通块,强连通块内点数最多的即为答案,还未尝试。其实。。。我怕是图想多了。数据量是100.就爆搜吧。好吧知道了开始。写的时候出了很多问题。每一个点都是有两种选择的,要么从之前的中间选一个组进入,要么单独建一个组。写的时候要注意强剪枝,zu>=ans就不ok了。开始写的>会超时。

代码:

#include<bits/stdc++.h>
using namespace std;
int mp[1010][1010];
int G[1010][1010];
int z[1010];///记录每个组的个数
int n;
const int INF=0x3f3f3f3f;
int ans=INF;
void dfs(int zu,int now){
   /// cout<<zu<<" %%% "<<now<<endl;
    if(zu>=ans)
        return;///说明不满足,剪枝

    if(now>n){///都分完了
        ans=min(ans,zu);
        return ;
    }
    for(int i=1;i<=zu;i++){///组数
        int tmp=0;
        for(int j=1;j<=z[i];j++){/// 组内。的个数///G[i][j].代表第i组第j个是谁,模拟vector
            int k=G[i][j];///k=i->j
            if(mp[now][k]==0)
                tmp++;
        }
        if(tmp==z[i])///可以放在i组内
        {
               G[i][z[i]+1]=now;
               z[i]++;
               dfs(zu,now+1);///分下一个
               G[i][z[i]]=0;
               z[i]--;
        }
    }///所有组数扫完了
   
            z[zu+1]=1;///新组
            G[zu+1][1]=now;///分到了当前的新组。
            dfs(zu+1,now+1);

}
int main()
{
    int m,a,b;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&a,&b);
        mp[a][b]=1;
        mp[b][a]=1;
    }
    z[1]=1;
    G[1][1]=1;
    dfs(1,1);
    printf("%d\n",ans);
}
/*

20
246

1 2
1 3
1 5
1 6
1 7
1 8
9 2
9 3
9 4
9 5
9 7
13 11
13 12
13 10
18 20
11 6
11 1
19 6
19 5
19 4
13 14
19 3
19 2
13 17
19 1
13 20
6 18
12 13
6 17
8 1
12 15
8 2
12 14
8 3
8 4
8 6
12 18
8 9
6 12
6 11
12 20
6 14
6 13
6 16
19 8
6 15
1 18
10 7
10 8
1 19
1 16
1 17
1 14
10 3
10 4
1 15
10 1
1 12
1 13
18 8
18 7
18 6
18 3
18 2
18 14
18 16
18 17
18 12
18 13
7 2
7 3
7 4
7 6
7 9
17 11
17 16
17 15
17 14
17 13
17 1
7 19
17 8
7 18
17 7
17 18
17 6
17 5
17 4
17 2
7 10
7 13
17 20
7 15
7 14
12 11
12 10
7 16
20 9
20 8
2 16
20 5
20 4
2 14
20 3
20 2
6 2
16 18
6 5
6 7
6 8
6 9
16 20
11 10
20 1
2 11
2 10
7 20
16 2
16 1
11 13
16 7
11 16
11 15
11 18
16 3
11 17
11 20
10 18
10 19
5 1
5 2
8 19
10 11
5 4
5 6
5 7
10 14
5 8
10 15
10 16
10 17
8 12
8 16
8 15
8 18
8 10
15 2
15 1
3 19
3 18
3 17
3 15
3 14
15 9
15 8
15 7
15 6
15 5
16 15
16 14
16 13
16 12
3 12
3 11
8 20
4 1
4 3
4 5
4 6
4 7
4 8
15 14
15 13
15 12
3 20
14 3
14 2
15 17
15 16
14 9
14 8
15 19
14 5
9 14
15 20
9 15
9 12
9 13
9 19
9 16
9 10
9 11
3 1
3 2
3 4
14 16
4 15
3 6
4 17
3 7
14 15
4 19
14 19
20 15
20 16
14 20
20 14
4 10
4 11
20 12
4 12
4 13
20 10
9 20
20 18
13 4
13 3
13 2
13 1
13 9
2 1
2 7
2 8
19 15
19 17
19 11
19 13
19 14
19 10
12 6
12 5
12 4
12 3
12 2
12 1
5 16
5 18
12 9
5 10
5 11
14 13
5 13
14 10
5 15
14 11
19 20

*/

就写写水题了呜呜呜。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值