UVA 10160 - Servicing Stations

来源:互联网 发布:图形界面c语言 知乎 编辑:程序博客网 时间:2024/04/19 14:06

题目大意:在一个城市放发电站,这个城市和直接邻接城市都会有电。问使所有城市都有电的最小放置发电站的个数。


解题思路:首先想到DFS,城市就是两种状态放发电站还是不放发电站 如此深搜下去可以得到最小的放置发电站个数,但35的数据规模是不允许不剪枝的。


1、放置发电站后,其产生的作用为0,即放置这个发电站后,有电的城市还是有电,没电的城市还是没电,也就是说放置发电站后,状态从无电变为有电的城市为0。(注意,有电的城市是可以重复有电的,即被多家不同的邻接发电站供电,放置发电站的城市也可以是有电的,只要城市本身没有发电站就行)这样的情况剪掉不再深搜下去。


2、在深搜到某一点时,他之前存在着没有电的点,而这个某一点之后的其他点即我们后面要搜到的点也没有与前面的这个无电的点直接邻接连通,那么意味着这趟搜索直到结束,这个无电的点也永远无电(不能再在这个城市放发电站,因为搜索过程已经到后面的点;也不能通过后续的点放发电站对他供电因为根本不直接连通邻接),显然不能满足覆盖全城市有电的条件,剪掉这种情况。

#include <cstdio>#define ll long longlong long st[40], later[40];int num, n, m;bool DFS(long long build, int step, int cur) {if (build == ((ll)1 << n) -1)return true;if (step == num)return false;for (int i = cur; i <= n; i++) {if (build == (build | st[i]))continue;if ((build | later[i]) != ((ll)1 << n) -1)return false;if (DFS(build | st[i], step + 1, cur + 1))return true;}}int main() {while (scanf("%d%d", &n, &m), n) {for (int i = 0; i < n; i++)st[i + 1] = (ll)1 << i;int a, b;for (int i = 0; i < m; i++) {scanf("%d%d", &a, &b);st[a] |= (ll)1 << (b - 1);st[b] |= (ll)1 << (a - 1);}later[n] = st[n];for (int i = n - 1; i > 0; i--)later[i] = later[i + 1] | st[i];for (num = 1; num <= n; num++) if (DFS((ll)0, 0, 1)) {printf("%d\n", num);break;}}return 0;}


0 0