zoukankan      html  css  js  c++  java
  • [POI2008]POD-Subdivision of Kingdom

    题目描述

    Byteasar, king of Byteotia, has finally decided to retire.

    He has two sons, however, and is unable to decide which one one of them should succeed him. Therefore he plans to split the kingdom into two halves, making each son a ruler.

    After the division, watchtowers have to be built along the roads connecting the halves. Obviously, building them will be costly, so ideally there should be as little roads between the halves as possible.

    Luckily, Byteotia consists of an even number of towns, connected by roads. Resulting from the division, each half-kingdom should contain half the towns. Each road connects (directly) two towns.

    The roads do not meet nor cross outside towns, though they can lead through flyovers or tunnels. Every two towns are directly connected by at most one road.

    Which exact towns should lie in which half of the kingdom is a matter of great importance. You may assume that the land outside the towns can be partitioned in such a way that the roads connecting towns lying in the same half will not cross the border.

    On the other hand, one watchtower has to be built by each road connecting towns from different halves.

    Task Write a programme that:

    reads the descriptions of towns and the roads connecting them from the standard input, determines such a partition of kingdom into halves that both the halves contain an equal number of towns and the number of roads connecting towns lying in different halves is minimum, writes out the result to the standard output.

    If more than one optimum partition exists, your programme should pick one of them arbitrarily.

    给定一个n个点的无向图,要求将点集分成大小相等的两个子集,使两个子集之间的边数最少

    输入输出格式

    输入格式:

    The first line of the standard input contains two integers and , separated by a single space, denoting the number of towns and number of roads respectively, , , .

    The towns are numbered from to .

    Each of the following lines contains two integers separated by a single space.

    The line no. (for ) contains the numbers and , ![](h…

    输出格式:

    Your programme should write out exactly one line to the standard output.

    It should contain integers separated by single spaces.

    These should be the numbers of towns belonging to the same half of the kingdom the town no. does, in an increasing order.

    输入输出样例

    输入样例#1:

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

    输出样例#1:

    1 2 6


    状压 + 搜索

    可以先预处理出来选中每个点后会增加哪些边

    然后再处理出前2^(n/2)中状态来

    既然已经处理出前2^(n/2)的状态了

    那不就可以求2^n的状态了吗?

    这样就可以直接暴力搜索组合了

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    const int M = 30 ;
    const int N = (1 << 14) + 5 ;
    using namespace std ;
    inline int read() {
        char c = getchar() ; int x = 0 , w = 1 ;
        while(c>'9'||c<'0') { if(c=='-') w = -1 ; c = getchar() ; }
        while(c>='0'&&c<='9') { x = x*10+c-'0' ; c = getchar() ; }
        return x*w ;
    }
    
    int n , m ;
    int e[M] , Num[M] ;
    int Ans = 1e9 , st ;
    inline int Count(int x) { return Num[x >> (n >> 1)] + Num[x - ((x >> (n >> 1)) << (n >> 1))] ; }
    void Dfs(int t , int k , int tot , int sit1 , int sit2) {
        if(k == (n >> 1)) {
            if(tot < Ans) st = sit1 , Ans = tot ;
            return ;
        }
        for(int i = t ; i <= n ; i ++)
            Dfs(i + 1 , k + 1 , tot + Count((e[i] & (sit2 ^ (1 << (i - 1))))) - Count(e[i] & sit1) , (sit1 | (1 << (i - 1))) , (sit2 ^ (1 << (i - 1)))) ;
        /*
    	Count((e[i] & (sit2 ^ (1 << (i - 1)))))相当于把这个点跟所有没选的点都给连接了一条边
    	Count(e[i] & sit1) 相当于把这个点跟所有选了的点的边都断掉 
    	*/
    }
    int main() {
        n = read() ; m = read() ;
        for(int i = 0 ; i < (1 << (n >> 1)) ; i ++) Num[i] = Num[i >> 1] + (i & 1) ;
        for(int i = 1 , u , v ; i <= m ; i ++) {
            u = read() , v = read() ;
            e[u] |= (1 << (v - 1)) ;
            e[v] |= (1 << (u - 1)) ;
        }
        Dfs(1 , 0 , 0 , 0 , (1 << n) - 1) ;
        for(int i = 1 ; i <= n ; i ++)
            if(st & (1 << (i - 1)))
                printf("%d ",i) ;
        return 0 ;
    }
    
  • 相关阅读:
    C#多线程编程实战(二)
    C#为什么要多线程开发(一)
    海康威视实时预览回调PS流用EasyRTMP向RTMP服务器推流中视频数据处理的代码
    CentOS "libc.so.6: version 'GLIBC_2.14' not found"解决方法,同理'GLIBC_2.15' not found"
    EasyRTMP结合海康HCNetSDK获取海康摄像机H.264实时流并转化成为RTMP直播推流(附源码)
    基于EasyDSS流媒体解决方案创建视频点播、短视频、视频资源库等视频播放系统
    EasyNVR是怎么做到Web浏览器播放RTSP摄像机直播视频延时控制在一秒内的
    EasyNVR depends on ffmpeg,yasm/nasm not found or too old. Use --disable-yasm for a crippledbuild
    EasyDSS流媒体服务器软件支持HTTPS-启用https服务申请免费证书
    EasyDSS流媒体服务器软件(支持RTMP/HLS/HTTP-FLV/视频点播/视频直播)-正式环境安装部署攻略
  • 原文地址:https://www.cnblogs.com/beretty/p/9724530.html
Copyright © 2011-2022 走看看