BNU 51645 ACM Battle【思维+爆搜】确实挺隐秘的一个爆搜题

224 篇文章 2 订阅

ACM Battle

Time Limit: 2000ms
Memory Limit: 262144KB
64-bit integer IO format:  %lld      Java class name:  Main
Type: 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •                   
  • 古往今来的各种传说中存在着很多魔法阵,它们的激活方式也各不相同。传说在北师大电子楼前的小花园里就有一个魔法阵,上次出现还是在很多很多很多年前,但是现在它又出现了!

    这时,小Q同学面无表情地说:“传说这个魔法阵都会在都会在来自远古的恶魔Awesome Crystal Monster(ACM)降临的时候出现,现在,这个时候终于要到来了吗!”话音未落,小Q同学已经走到了魔法阵前,取出一个小瓶,开始用瓶中的圣水激活这个魔法阵,“你们快退后,这里就交给我了!”

    这个魔法阵由一些点和一些连接这些点的边构成,当小Q同学把圣水滴在一个点上时,和这个点相连的所有边就会被点亮并发出神圣的光芒,当魔法阵所有的边都点亮的时候,就会出现强大的神圣力量。但是小Q同学拥有的圣水非常有限,只有10滴,现在小Q同学想知道他最少可以用多少滴圣水点亮整个魔法阵,如果耗尽圣水也不能点亮,就只能打出一波GG了。

    Input

    第一行包含一个正整数T(\leq 20),表示测试数据的组数,

    对于每组测试数据,

    第一行是两个整数n(1 \leq n \leq 1000)m(1 \leq m \leq 2000),表示魔法阵的点数和边数,

    接下来m行,每行包含两个整数u,v(1 \leq u,v \leq n),表示有一条边连接了u号点和v号点。

    Output

    对于每组测试数据,如果使用不超过10滴圣水可以点亮整个魔法阵,输出最少需要的圣水滴数,否则输出"GG"(不含引号)。

    Sample Input

    2
    4 3
    1 2
    1 3
    1 4
    4 4
    1 2
    2 3
    3 4
    4 1

    Sample Output

    1
    2

    Hint

    对于第一组样例,最优方案是在1号点滴一滴圣水,

    对于第二组样例,一个最优方案是在1号点和3号点各滴一滴圣水。

    Source

    Author

    Mashiro

    思路:


    一开始读完题下意识的就觉得是最小点覆盖问题,然而忘记这个图可能会存在(奇数长度)环的问题了,直接闭着眼睛去搞了一发。

    然后发现不能处理变成二分图。

    当然也不能树型Dp去求最小点覆盖数。

    问题焦点肯定锁定在10个点上来。

    所以我们着重考虑10个点的问题。

    对于这十个点的枚举我想了半天,后来才发现不妨去枚举边。(这题的爆搜思路还是挺隐秘的,反正窝不太常见这种题,我不太能一眼看出来,要思考好久好久啊-----);

    锻炼了这样的能力,蛮开心。



    我们要染到所有的边,所以我们不妨去枚举边,对于一条边来讲:

    ①如果其之前选的点之中选择过了这条边的某个点,那么这条边就已经被染上了不用去管。

    ②如果这条边没有被染过,那么对应有两种选择,要么去染u,要么去染v.如果就单单这一条边我们就要将两个点都处理了的话是没有必要的,所以我们这里枚举一种情况即可。

    那么对于每一条边我们都去枚举情况的话,时间复杂度可是要达到O(2^m)的啊;

    看起来是这样的,回归焦点,我们一旦已经枚举过了10个点出来,而当前边还需要选择一个点去选择,那么当前情况就可以剪枝掉。

    所以最坏的时间复杂度其实是O(2^10*m);

    那么我们爆搜处理维护最小值即可


    Ac代码:


    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    using namespace std;
    struct node
    {
        int x,y;
    }a[2500];
    int n,m;
    int ans;
    int vis[2500];
    void Dfs(int u,int sum)
    {
        if(sum>10)return ;
        if(u==m)
        {
            ans=min(ans,sum);
            return ;
        }
        if(vis[a[u].x]==1||vis[a[u].y]==1)Dfs(u+1,sum);
        else
        {
            vis[a[u].x]=1;
            Dfs(u+1,sum+1);
            vis[a[u].x]=0;
            vis[a[u].y]=1;
            Dfs(u+1,sum+1);
            vis[a[u].y]=0;
        }
        return ;
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            memset(vis,0,sizeof(vis));
            scanf("%d%d",&n,&m);
            for(int i=0;i<m;i++)scanf("%d%d",&a[i].x,&a[i].y);
            ans=0x3f3f3f3f;
            Dfs(0,0);
            if(ans<=10)
            printf("%d\n",ans);
            else printf("GG\n");
        }
    }









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

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值