UOJ37. [2014] Tsinghua training Themes

http://uoj.ac/problem/37

answer

Entitled Let's find how many can make this set of edges and strengthen the country connectivity.

To complement conversion look, this demand is not strong FIG communication program number.

We consider such a complete view of the situation after compression point, since it is not strongly connected, then it is a \ (DAG \) .

Recall directed graph \ (DAG \) method for the enumeration.

Was added into each new one degree \ (0 \) point, even prior to the edge point. But this time we can not guarantee that we enumerated point is all the degrees \ (0 \) , so we also need to inclusion and exclusion.
\ [F [S] = \
sum_ {T \ subset S} (- 1) ^ {| T |} f [ST] 2 ^ {edge (S, ST)} \] observed again and points receiving repellent coefficient about parity, because each time we have a strong point of the connected component.

So we set \ (deg [s] \) represents \ (s \) collection is a \ (DAG \) , if obtained this array, then we use it is minus Complete Works answer.

We then set \ (D [s] \) represents \ (S \) set is divided into an odd number of programs strongly connected component, \ (S [S] \) represents is divided into an even number of programs strongly connected components.

Transfer:
\ [DAG [S] = \ sum_ {T \ S} Subset (D [S] -S [S]) * 2 ^ {Edge (T, ST) + Edge (ST, ST)} \]
Finally, add even his own number because our program is the inclusion-exclusion factor has somehow, just let \ (ST \) shrink after completing point become a \ (DAG \) on the line, so the legal side of the set is complete works.

Our final answer \ (f [s] \) represents \ (S \) scheme set strongly connected number, \ (D \) and \ (S \) transferred are:
\ [D [S] = \ sum_ { T \ subset S} f [T ] * S [ST] \]

\[ S[S]=\sum_{T\subset S}f[T]*D[S-T] \]

Code

#include<bits/stdc++.h>
#define N 16
#define M 225
using namespace std;
typedef long long ll;
const int mod=1e9+7;
int n,m;
ll D[1<<N],S[1<<N],ci[N*N],f[1<<N];
bitset<M>in[1<<N],out[1<<N];
inline void MOD(ll &x){x=x>=mod?x-mod:x;}
inline ll rd(){
  ll x=0;char c=getchar();bool f=0;
  while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
  while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
  return f?-x:x;
}
inline int calc(int s,int t){return (out[s]&in[t]).count();}
int main(){
  n=rd();m=rd();
  int u,v;
  int maxn=(1<<n)-1;
  ci[0]=1;
  for(int i=1;i<=n*n;++i)ci[i]=ci[i-1]*2%mod;
  for(int i=1;i<=m;++i){
    u=rd();v=rd();
    for(int j=1;j<=maxn;++j){
      if(j&(1<<u-1))out[j][i]=1;
      if(j&(1<<v-1))in[j][i]=1;
    }
  }
  S[0]=1;
  for(int i=1;i<=maxn;++i){
    f[i]=ci[calc(i,i)];
    for(int s=(i-1)&i;s;s=(s-1)&i){
      MOD(f[i]=(f[i]-(D[s]-S[s])*ci[calc(s,i-s)+calc(i-s,i-s)]%mod+mod));
      if((s&(i&-i))==0)continue;
      MOD(D[i]+=f[s]*S[i-s]%mod);
      MOD(S[i]+=f[s]*D[i-s]%mod);
    }
    MOD(f[i]=(f[i]-(D[i]-S[i]))%mod+mod);
    MOD(D[i]+=f[i]);
  }
  cout<<f[maxn];
  return 0;
}

Guess you like

Origin www.cnblogs.com/ZH-comld/p/11123386.html