• Gym


    题面

    题意:给你n(20)个点,m(40条边),让你给每条边染一种颜色,白色0元,红色2元,蓝色1元,现在要保证每一条白边相邻的有一条红边,问至少花多少

    题解:刚开始想的时候,好像觉得只用染红色和白色就够了?乱搞一通就发现不对了

            例如:5个点,5条边:1 2,   2 3  ,  3 4 , 4 5 , 5 2 .  如果只用红白,则答案为2条红边,2*2=4  但实际上,如果2 5染红,3 4染蓝,答案为3

            所以我们重新思考:什么时候染蓝色?

            我们假设一条边,如果染了红色,则他的2个端点,就标记为红色,如果我们枚举每个点是否红色(2^20),然后再看这个图

            我们发现,此时如果存在一条边的两个端点都没被染红,那么把这条边染蓝更优.

            所以我们利用状压,枚举每个点染红的状态(注意这个状态其实也是由边统计来的)

            dp[i]表示i集合为红的最小花费    dp[i+t]=dp[i]+2;  t=i | (1<<u) | (1<<v)  (其实u,v都要减一,不过在读入的时候处理掉了)

            然后再枚举每个状态,看蓝色的花费,统计出最小的答案

           

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int n,m,a[45],b[45],f[1024*1024+10];
     4 int main()
     5 {
     6     scanf("%d%d",&n,&m);
     7     for (int i=1;i<=m;i++) scanf("%d%d",&a[i],&b[i]),a[i]--,b[i]--;
     8     int nn=1<<n;
     9     for (int i=0;i<nn;i++) f[i]=(int)1e8;
    10     f[0]=0;
    11     for (int i=0;i<nn;i++)
    12     {
    13         if (f[i]!=(int)(1e8))
    14         {
    15             for (int j=1;j<=m;j++)
    16             {
    17                 int t=i|(1<<a[j])|(1<<b[j]);
    18                 f[t]=min(f[t],f[i]+2);
    19             }
    20         }
    21     }
    22     int ans=(int)(1e8);
    23     for (int i=0;i<nn;i++)
    24     {
    25         int qq=f[i];
    26         for (int j=1;j<=m;j++)
    27         {
    28             if ((i>>a[j])%2==0 && (i>>b[j])%2==0) qq++; 
    29         }
    30         ans=min(ans,qq);
    31     }
    32     cout<<ans<<endl;    
    33 }

                              

  • 相关阅读:
    GDI绘图1——自定义函数
    GDI绘图1——枚举
    打箱子&地形&鼠标点击移动总结
    使用Playmaker1——基础使用
    图形用户编程工具集比较--转
    Java中抽象类和接口的区别
    myeclipse安装 配置Maven3
    在Ubuntu上安装hadoop2.2.0的一些记录
    Hadoop2.2.0安装配置手册!完全分布式Hadoop集群搭建过程
    获得hadoop源码网址
  • 原文地址:https://www.cnblogs.com/qywhy/p/10633376.html
Copyright © 2020-2023  润新知