zoukankan      html  css  js  c++  java
  • 1140 分珠 dfs

    时间限制:500MS  内存限制:65536K
    提交次数:24 通过次数:18

    题型: 编程题   语言: G++;GCC

     

    Description

    如下图所示,有若干珠子,每颗珠子重量不同,珠子之间有一些细线将它们连在一起。现要求切断一些细线,将它们分成两部分,分割后,单独每一部分的珠子仍保持相连,且要求尽量做到两部分总重相等或相差最少。
    请编一程序,给定珠子个数、每颗珠子的重量以及珠子之间的连接情况,输出按上述要求分割后两部分总重的差值的绝对值。
    




    输入格式

    第一行有两个数N与M(1<=N,M<=10),N为珠子个数(珠子编号依次为1,2,3,...,N),M为连接珠子的细线数目。第二行为N个正整数,分别为N个珠子的重量。此后M行,每行两个数X与Y,表示珠子X与珠子Y由细线相连。



    输出格式

    按要求分割后两部分总重的差值的绝对值。



     

    输入样例

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



     

    输出样例

    1

    题意:给出一个图,将图分成两半,每一部分都需要保持连通,问分开能得到的最小差值

    思路:n最大只有10,可以枚举n的所有组合作为其中一半,然后判断这一半所有节点是否连通,然后再判断剩下的所有节点是否连通,从所有组合中得到最小差值

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <cmath>
     6 #include <queue>
     7 #include <vector>
     8 using namespace std ;
     9 int a[12], G[12][12], vis[12] ;
    10 int n, m, sx ;
    11 vector<int> vc;//vc里面存储当前枚举到的节点,并判断连通性
    12 void dfs(int cur)//dfs标记
    13 {
    14     vis[cur] = 1 ;
    15     for(int i = 1; i <= n; ++i)
    16         if(!vis[i] && G[cur][i]) dfs(i) ;
    17 }
    18 int _union()//判断连通性
    19 {
    20     int leap = 0 ;
    21     for(int i = 0; i < sx; ++i){
    22             leap = 0 ;
    23             for(int j = 0; j < sx; ++j) if(i != j){
    24                     if(G[ vc[i] ][ vc[j] ]){
    25                         leap = 1;
    26                         break ;
    27                     }
    28                 }
    29             if(!leap) break ;
    30         }
    31         if(!leap) return 0 ;
    32         else return 1 ;
    33 }
    34 int check()
    35 {
    36     sx = vc.size() ;
    37     if(vc.size() > 2) if(!_union()) return 0 ;
    38     for(int k = 1; k <= n; ++k) if(!vis[k]){
    39             dfs(k) ;
    40             break ;
    41         }
    42     for(int i = 1; i <= n; ++i)
    43         if(!vis[i]) return 0 ;
    44     return 1 ;
    45 }
    46 int main()
    47 {
    48     int u, v, sum = 0, mi = 1 << 25, flag ;
    49     memset(G, 0, sizeof G) ;
    50     scanf("%d%d",&n,&m) ;
    51     for(int i = 1; i <= n; ++i){
    52         scanf("%d",&a[i]) ;
    53         sum += a[i] ;
    54     }
    55     flag = sum >> 1 ;//以sum的一半作为flag
    56     for(int i = 1; i <= m ; ++i){
    57         scanf("%d%d",&u,&v) ;
    58         G[u][v] = 1 ;
    59         G[v][u] = 1 ;
    60     }
    61     for(int i = 1; i < (1 << n); ++i)//枚举所有的组合
    62     {
    63         int now = 0 ;
    64         vc.clear() ;
    65         memset(vis, 0, sizeof vis) ;
    66         for(int j = 1; j <= n; ++j)
    67             if(i & (1 << (j - 1))){
    68                 vis[j] = 1 ;
    69                 now += a[j] ;
    70                 vc.push_back(j) ;
    71             }
    72         if(now < flag || now >= mi) continue ;
    73         if(check()) mi  = now ;
    74     }
    75     printf("%d
    ",abs(sum - 2 * mi)) ;
    76 }
    View Code

    修改一下,当vc.size() == 2 时, 也要判断这两个节点的连通性 

  • 相关阅读:
    连载日记
    自我介绍
    test0710 二分专题
    test0709 搜索专题
    test0705
    test0704
    [题解] [HNOI2015]落忆枫音
    test0606
    test0523
    备份
  • 原文地址:https://www.cnblogs.com/orchidzjl/p/4527871.html
Copyright © 2011-2022 走看看