Codeforces Round #454 (Div. 2, based on Technocup 2018 Elimination Round 4) E. Party [dp II][bitmasks]

题目:http://codeforces.com/contest/907/problem/E

题意:最多22个客人,每次选择一个人,可以使他的所有朋友互相都成为朋友,输出能使所有人互相都成为朋友的最少的选择次数和选择顺序

分析:数位dp,用dp[i]表示第i个状态里的人都互相是朋友所需要的最少选择次数,pre存储上一次的状态和上一次选择的人,转移的时候则需要选择已经在这个朋友圈里的人继续扩张朋友圈。要注意特判当前都已经互相为朋友的情况。

(因为数据比较小,而且合法情况非常多,也可以用随机化算法ac)

代码:

 1 #define _CRT_SECURE_NO_DEPRECATE
 2 #pragma comment(linker, "/STACK:102400000,102400000")
 3 #include<iostream>  
 4 #include<cstdio>  
 5 #include<fstream>  
 6 #include<iomanip>
 7 #include<algorithm>  
 8 #include<cmath>  
 9 #include<deque>  
10 #include<vector>
11 #include<bitset>
12 #include<queue>  
13 #include<string>  
14 #include<cstring>  
15 #include<map>  
16 #include<stack>  
17 #include<set>
18 #include<functional>
19 #define pii pair<int, int>
20 #define mod 1000000007
21 #define mp make_pair
22 #define pi acos(-1)
23 #define eps 0.00000001
24 #define mst(a,i) memset(a,i,sizeof(a))
25 #define all(n) n.begin(),n.end()
26 #define lson(x) ((x<<1))  
27 #define rson(x) ((x<<1)|1) 
28 #define inf 0x3f3f3f3f
29 typedef long long ll;
30 typedef unsigned long long ull;
31 using namespace std;
32 const int maxn = 1e5 + 5;
33 int dp[1 << 23];
34 pii pre[1 << 23];
35 int fri[25];
36 int main()
37 {
38     ios::sync_with_stdio(false);
39     cin.tie(0); cout.tie(0);
40     int i, j, k, m, n;
41     cin >> n >> m;
42     int ta, tb;
43     for (int i = 1; i <= m; ++i)
44     {
45         cin >> ta >> tb;
46         ta--, tb--;
47         fri[ta] |= (1 << tb);
48         fri[tb] |= (1 << ta);
49     }
50     int mode = 1;
51     for (int i = 0; i < n; ++i)
52     {
53         if (fri[i] != (1 << n) - 1 - (1 << i))mode = 0;
54     }
55     if (mode) { cout << "0" << endl; return 0; }
56     mst(dp, -1);
57     mst(pre, -1);
58     for (int i = 0; i < n; ++i)
59         dp[1 << i] = 0, pre[1 << i] = mp(-1, -1);
60     for (int i = 1; i < (1 << n); ++i)
61     {
62         if (dp[i] == -1)continue;
63         for (int j = 0; j < n; ++j)
64         {
65             if (i >> j & 1)
66             {
67                 int newmode = i | fri[j];
68                 if (dp[newmode] == -1 || (dp[newmode] > dp[i]))
69                 {
70                     dp[newmode] = dp[i] + 1;
71                     pre[newmode] = mp(i, j);
72                 }
73             }
74         }
75     }
76     cout << dp[(1 << n) - 1] << endl;
77     pii now = pre[(1 << n) - 1];
78     vector<int>ans;
79     while (now.first != -1)
80     {
81         ans.push_back(now.second);
82         now = pre[now.first];
83     }
84     reverse(all(ans));
85     for (auto it : ans)cout << it+1 << " ";
86     return 0;
87 }

 

posted @ 2017-12-26 15:13  Meternal  阅读(250)  评论(0编辑  收藏  举报