TC SRM 696 DIV2 1000 Clicountingd2

Problem Statement

给定一个n*n的矩阵,表示一个无向图。

0:不相邻;1:相邻;?:未知.

其中'?'的关系有m个(对称的2个算一种),从而有2^m种情况,求每种情况的最大团大小之和。

n≤20,m≤20,保证矩阵合法。

Tutorial

枚举每个点集,考虑能否形成团,如果关系中有0则跳过,对于能形成团的的,考虑用到了哪些未知关系,把这个处理成集合的形式,然后用高维前缀和求一下最大值就好了。

PS:最开始想到高维前缀和时懵了一下,没有想下去,去想枚举未知关系,不知所措,导致TC首秀很失败啊==

 1 #include <set>
 2 #include <ctime>
 3 #include <queue>
 4 #include <cstdio>
 5 #include <bitset>
 6 #include <cctype>
 7 #include <bitset>
 8 #include <cstdlib>
 9 #include <cassert>
10 #include <cstring>
11 #include <iostream>
12 #include <algorithm>
13 #define inf (1<<30)
14 #define INF (1ll<<62)
15 #define fi first
16 #define se second
17 #define rep(x,s,t) for(register int x=s,t_=t;x<t_;++x)
18 #define per(x,s,t) for(register int x=t-1,s_=s;x>=s_;--x)
19 #define prt(x) cout<<#x<<":"<<x<<" "
20 #define prtn(x) cout<<#x<<":"<<x<<endl
21 #define pb(x) push_back(x)
22 #define hash asfmaljkg
23 #define rank asfjhgskjf
24 #define y1 asggnja
25 #define y2 slfvm
26 using namespace std;
27 typedef long long ll;
28 typedef pair<int,int> ii;
29 const int maxn=20;
30 int n;
31 int mx[1<<maxn];// 
32 int b[1<<maxn];
33 int id[maxn][maxn];
34 int v[maxn];
35 int d[maxn];//相邻点 
36 
37 template<class T>inline void Max(T &x,T y){if(x<y)x=y;}
38 template<class T>inline void Min(T &x,T y){if(x>y)x=y;}
39 
40 class Clicountingd2 {
41 public:
42     int count(vector <string> g) {
43         n=g.size();
44         int tot=0;
45         rep(i,0,n)b[1<<i]=i;
46         rep(i,0,n)d[i]=0;
47         rep(i,0,n)v[i]=0;
48         rep(i,0,n)rep(j,0,n)id[i][j]=0;
49         
50         rep(i,0,n)rep(j,0,n){
51             if(i==j||g[i][j]=='1'||g[i][j]=='?')
52                 d[i]|=1<<j;
53             if(g[i][j]=='?'){
54                 v[i]|=1<<j;
55                 if(i>j)id[i][j]=id[j][i];
56                 else id[i][j]=tot++;
57             }
58         }    
59         memset(mx,0,sizeof mx);
60         rep(i,0,1<<n){
61             bool ok=true;
62             int cnt=0;
63             for(int t=i;t;t-=t&-t){
64                 int k=b[t&-t];
65                 cnt++;
66                 if((d[k]&i)!=i){
67                     ok=false;
68                     break;
69                 }
70             }
71             if(!ok)continue;
72             int flag=0;
73             for(int t=i;t;t-=t&-t){
74                 int k=b[t&-t];
75                 for(int s=v[k]&i;s;s-=s&-s){
76                     int l=b[s&-s];
77                     flag|=1<<id[k][l];
78                 }
79             }
80             Max(mx[flag],cnt);
81         }
82         rep(i,0,tot)rep(j,0,1<<tot)
83             if(j>>i&1)
84                 Max(mx[j],mx[j^(1<<i)]);
85         int ans=0;
86         rep(i,0,1<<tot)
87             ans+=mx[i];
88         return ans;
89     }
90 };
View Code

 

 

  

 

posted @ 2016-08-11 10:44  ShinFeb  阅读(244)  评论(0编辑  收藏  举报