zoukankan      html  css  js  c++  java
  • AtCoder Beginner Contest 187 F

    题目链接

    点我跳转

    题目大意

    给你一张完全图,你可以删除任意数量的边

    要求删除完后剩余的所有子图必须是完全图

    问完全子图数量最少是多少

    解题思路

    定义 (ok[i]) 表示状态为 (i) 时所对应的点构成的图是否为完全图 ((1) 为是 , (0) 为否)

    判断完全图可直接暴力枚举任意两点检查是否有边

    定义 (dp[i]) 表示状态为 (i) 时所对应的点构成的所有子图都为完全图,且子图数最小

    其中 (dp[0] = 0)

    那么不难得到当 (ok[j] = 1)

    (dp[i] = min(dp[i] , dp[i) ^(j] + 1)) , ( (j)(i) 的子集 )

    答案为 (dp[1 << n - 1])

    AC_Code

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1LL << 19 , M = 20;
    int n , m , dp[N] , ok[N] , g[M][M];
    signed main()
    {
    	cin >> n >> m;
    	for(int i = 1 ; i <= m ; i ++)
    	{
    		int x , y;
    		cin >> x >> y;
    		g[x][y] = g[y][x] = 1;
     	}
     	int sum = 1 << n;
    	for(int i = 0 ; i < sum ; i ++)
    	{
    		ok[i] = 1;
    		for(int j = 1 ; j <= n ; j ++) if(i >> (j - 1) & 1) 
    		{
    			for(int k = j + 1 ; k <= n ; k ++) if(i >> (k - 1) & 1)		
    			{
    				if(!g[j][k]) { ok[i] = 0 ; break ; }		
    			}
    			if(!ok[i]) break ;
    		} 
    		dp[i] = 1e9; 
    	}
    	dp[0] = 0;
    	for(int i = 0 ; i < sum ; i ++)
    	{
    		for(int j = i ; j ; j = (j - 1) & i) if(ok[j]) 
    		{
    			dp[i] = min(dp[i] , dp[i ^ j] + 1);
    		}
    	}
    	cout << dp[sum - 1] << '
    ';
    	return 0;
    }
    
  • 相关阅读:
    java基础—面向对象2
    java基础—java读取properties文件
    java基础—super关键字
    java基础—this关键字
    java基础—object类
    java基础—equals方法
    java基础—哈希编码
    Struct2(五)处理表单
    struct2(四)编写Struct2 的Action
    Struct2(三) Struct2 标签
  • 原文地址:https://www.cnblogs.com/StarRoadTang/p/14224930.html
Copyright © 2011-2022 走看看