解:搜索......
我们可以每次选择分支少的搜索,或者说,贪心的搜索当前更优的决策。
每一层把能剪的点搞出来,按照度数/SIZ排序,然后依次搜索。加个最优化剪枝就完事了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <bits/stdc++.h> 2 3 const int N = 310, INF = 0x3f3f3f3f; 4 5 struct Edge { 6 int nex, v; 7 }edge[N << 1]; int tp; 8 9 int e[N], siz[N], in[N], n, ans = INF; 10 int v[N][N]; 11 bool del[N], vis[N]; 12 13 inline bool cmp(const int &a, const int &b) { 14 //return in[a] > in[b]; 15 return siz[a] > siz[b]; 16 } 17 18 inline void add(int x, int y) { 19 tp++; 20 edge[tp].v = y; 21 edge[tp].nex = e[x]; 22 e[x] = tp; 23 return; 24 } 25 26 void DFS_1(int x, int f) { 27 siz[x] = 1; 28 for(int i = e[x]; i; i = edge[i].nex) { 29 int y = edge[i].v; 30 if(y == f) continue; 31 DFS_1(y, x); 32 siz[x] += siz[y]; 33 } 34 return; 35 } 36 37 void DFS(int k, int d) { 38 if(k >= ans) return; 39 v[d][0] = 0; 40 for(int x = 1; x <= n; x++) { 41 if(del[x] || !vis[x]) continue; 42 /// vis[x] 43 for(int i = e[x]; i; i = edge[i].nex) { 44 int y = edge[i].v; 45 if(vis[y] || del[y]) continue; 46 v[d][++v[d][0]] = y; 47 } 48 } 49 50 if(!v[d][0]) { 51 ans = std::min(ans, k); 52 return; 53 } 54 55 std::sort(v[d] + 1, v[d] + v[d][0] + 1, cmp); 56 for(int i = 1; i <= v[d][0]; i++) { 57 vis[v[d][i]] = 1; 58 } 59 k += v[d][0] - 1; 60 for(int i = 1; i <= v[d][0]; i++) { 61 int x = v[d][i]; 62 del[x] = 1; 63 vis[x] = 0; 64 DFS(k, d + 1); 65 vis[x] = 1; 66 del[x] = 0; 67 } 68 for(int i = 1; i <= v[d][0]; i++) { 69 vis[v[d][i]] = 0; 70 } 71 return; 72 } 73 74 int main() { 75 76 // freopen("disease.in", "r", stdin); 77 // freopen("disease.out", "w", stdout); 78 79 int m; 80 scanf("%d%d", &n, &m); 81 for(int i = 1, x, y; i <= m; i++) { 82 scanf("%d%d", &x, &y); 83 add(x, y); add(y, x); 84 in[x]++; in[y]++; 85 } 86 DFS_1(1, 0); 87 vis[1] = 1; 88 DFS(1, 0); 89 90 printf("%d ", ans); 91 return 0; 92 }