• Codeforces 164 D Minimum Diameter


    题目链接~~>

    做题感悟:越来越感觉CF的题非常好,非常有深度。

    解题思路:

                     这题须要注意 k 的大小。由于 k 仅仅有 30 个,终于形成的点的直径一定是某个确定的值,所以我们能够枚举这个值。然后把大于这个值的边都取消(删除不大于k 个点),这样不断二分剩下点的最小直径。每次二分的时候推断是否合法。

    这里推断是否合法非常重要。由于这须要用dfs去枚举,一不小心就会超时。dfs 在枚举删除每一个点的时候主要枚举两个方面。(1)假设想删除与当前点相连的全部边,能够选择删除全部与之相连的点 (2)能够单独删除此点,然后与之相连的全部边都删除了。这里有一个剪枝:假设以下删除所达到的状态不如上面的优就不继续深搜下去了。由于到达当前点所形成的状态是一样的(都把与1 ~ x 节点相连的边都删除了),就看剩下能够删除点多的必然优。

    代码:

    #include<iostream>
    #include<sstream>
    #include<map>
    #include<cmath>
    #include<fstream>
    #include<queue>
    #include<vector>
    #include<sstream>
    #include<cstring>
    #include<cstdio>
    #include<stack>
    #include<bitset>
    #include<ctime>
    #include<string>
    #include<cctype>
    #include<iomanip>
    #include<algorithm>
    using namespace std  ;
    #define INT __int64
    #define L(x)  (x * 2)
    #define R(x)  (x * 2 + 1)
    const int INF = 0x3f3f3f3f ;
    const double esp = 0.0000000001 ;
    const double PI = acos(-1.0) ;
    const int mod = 1e9 + 7 ;
    const int MY = 1400 + 5 ;
    const int MX = 1010 + 5 ;
    int num ,n ,k ;
    vector<int>G[MX] ;
    int d[MX*MX] ,g[MX][MX] ,vis[MX] ;
    struct node
    {
        int x ,y ;
    }P[MX] ;
    bool dfs(int cnt ,int m) // cnt 代表编号 。m 代表删除的边数
    {
        if(cnt > n)     return true ;
        if(vis[cnt])    return dfs(cnt + 1 ,m) ;
        for(int i = 0 ;i < (int)G[cnt].size() ; ++i)
        {
             m += !vis[G[cnt][i]] ;
             vis[G[cnt][i]]++ ;
        }
        if(m <= k && dfs(cnt + 1 ,m))
                   return true ;
        int temp = m ;
        for(int i = 0 ;i < (int)G[cnt].size() ; ++i)
        {
            vis[G[cnt][i]]-- ;
            m -= !vis[G[cnt][i]] ;
        }
        if(G[cnt].size() != 1)
        {
            vis[cnt]++ ;
            if(m + 1 <= k && m + 1 < temp && dfs(cnt+1 ,m+1))
                return  true ;
            vis[cnt]-- ;
        }
        return false ;
    }
    bool judge(int dist)
    {
        memset(vis ,false ,sizeof(vis)) ;
        for(int i = 1 ;i <= n ; ++i)
             G[i].clear() ;
        for(int i = 1 ;i < n ; ++i)
          for(int j = i+1 ;j <= n ; ++j)
              if(g[i][j] > dist)
              {
                  G[i].push_back(j) ;
                  G[j].push_back(i) ;
              }
        return  dfs(1 ,0) ;
    }
    int binary_search(int le ,int rt)  //
    {
        int mid ;
        while(le < rt)
        {
           mid = (le + rt)>>1 ;
           if(judge(d[mid]))  rt = mid ;
           else  le = mid + 1 ;
        }
        return le ;
    }
    int main()
    {
        //freopen("input.txt" ,"r" ,stdin) ;
        while(~scanf("%d%d" ,&n ,&k))
        {
            num = 0 ; d[0] = 0 ;
            for(int i = 1 ;i <= n ; ++i)
               scanf("%d%d" ,&P[i].x ,&P[i].y) ;
            for(int i = 1 ;i < n ; ++i)
              for(int j = i+1 ;j <= n ; ++j)
                d[++num] = g[i][j] = (P[i].x-P[j].x)*(P[i].x-P[j].x) + (P[i].y - P[j].y)*(P[i].y-P[j].y) ;
            sort(d ,d + num + 1) ;
            num = unique(d ,d+num+1) - d - 1 ;
            int mx = binary_search(0 ,num) ; //   二分查找最小直径
            judge(d[mx]) ;
            bool first = false ;
            for(int i = n ;i >= 1 ; --i)
              if(vis[i])
              {
                  if(first)  putchar(' ') ;
                  printf("%d" ,i) ;
                  k-- ;
                  first = true ;
              }
            for(int i = n ;i >= 1 && k > 0 ; --i)
               if(!vis[i])
               {
                   if(first)  putchar(' ') ;
                   printf("%d" ,i) ;
                   k-- ;
                   first = true ;
               }
            cout<<endl ;
        }
        return 0 ;
    }
    
    


  • 相关阅读:
    Unity3D 开发之shader教程(浅谈光照之漫反射diffuse)
    Unity3D 开发之shader教程(实现圆角矩形)
    Unity3D 开发之shader教程(实时swirl 扭曲漩涡效果)
    lerp function(线性插值计算)
    关于Lua以及UniLua的学习与笔记(随时更新)
    Android SDK Manager 更新
    Mac OS X 安装protobuf 2.6.1
    IDFactory int类型ID生成器
    Android TextView 添加部分文字高亮,点击功能
    Android MonkeyRunner 功能测试 自动执行 挂机脚本
  • 原文地址:https://www.cnblogs.com/yfceshi/p/7020171.html
Copyright © 2020-2023  润新知