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\n",abs(sum - 2 * mi)) ;
76 }
View Code

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

posted @ 2015-05-25 14:59  JL_Zhou  阅读(466)  评论(0编辑  收藏  举报