HDU-5556 Land of Farms(无向图的最大独立集)

来源:互联网 发布:织梦cms 地区分站 编辑:程序博客网 时间:2024/06/10 00:32

题意:

一个N*M的矩阵,其中“.”代表空地,“0-9”代表古代建筑,如果选择了一个编号的古代建筑去重新建立,那么其对应所有该编号的古建筑都要被建立起来,如果在空地上建筑,可以只选择建立当前点。问最多能够建立多少个建筑,并且建立的所有建筑中每两个建筑不相邻,即没有公共边。

思路:

很容易想到是求最大独立集,将图中所有的两两限制关系全部抽象为边即可,但会发现将边抽象出来之后是一个无向图,不能构成一个二分图,所有需要利用最大团的BK算法去求(链接),无向图的最大独立集数 == 其补图的最大团数。

链接中的两种算法,前者会超时,后者才可以过,而且贼快= =,之前做的一道最大团的题也是后者算法快,以后求极大团才用前者,最大团全用后者吧(事实表明)。

代码:

#include <bits/stdc++.h>using namespace std;char s[15][15];int t, n, m, cnt;int used[15], _num[105][105];int match[105], vis[105];bool mp[105][105];  int best, num[105];  bool dfs(int *adj, int total, int cnt)  {      int t[105], k;      if(total == 0)      {          if(cnt > best)          {              best = cnt;              return true;         }          return false;      }      for(int i = 0; i < total; ++i)      {          if(cnt+total-i <= best) return false;          if(cnt+num[adj[i]] <= best) return false;         k = 0;          for(int j = i+1; j < total; ++j)          if(!mp[adj[i]][adj[j]]) t[k++] = adj[j];          if(dfs(t, k, cnt+1)) return true;      }      return false;  }  void work()  {      int adj[105], k;      best = 0;      for(int i = cnt; i >= 1; --i)      {          k = 0;          for(int j = i+1; j <= cnt; ++j)          if(!mp[i][j]) adj[k++] = j;        dfs(adj, k, 1);         num[i] = best;      }}int main(){//freopen("in.txt", "r", stdin);scanf("%d", &t);for(int _ = 1; _ <= t; ++_){memset(match, -1, sizeof match);memset(used, 0, sizeof used);memset(mp, 0, sizeof mp);scanf("%d %d", &n, &m);cnt = 0;for(int i = 1; i <= n; ++i)scanf("%s", s[i]+1);for(int i = 1; i <= n; ++i)for(int j = 1; j <= m; ++j){if(s[i][j] == '.'){_num[i][j] = ++cnt;int tx = i-1, ty = j-1;if(tx > 0)mp[cnt][_num[tx][j]] = mp[_num[tx][j]][cnt] = 1;if(ty > 0)mp[cnt][_num[i][ty]] = mp[_num[i][ty]][cnt] = 1;}else{int tmp;if(used[s[i][j]-'0'] != 0)tmp = used[s[i][j]-'0'];else tmp = ++cnt, used[s[i][j]-'0'] = cnt;_num[i][j] = tmp;int tx = i-1, ty = j-1;if(tx > 0 && tmp != _num[tx][j])mp[tmp][_num[tx][j]] = mp[_num[tx][j]][tmp] = 1;if(ty > 0 && tmp != _num[i][ty])mp[tmp][_num[i][ty]] = mp[_num[i][ty]][tmp] = 1;}}work();printf("Case #%d: %d\n", _, best);}return 0;}


继续加油~