题解CF11D A Simple Task

题目:CF11D A Simple Task

状压!但是细节很多,不注意会TWAT
1.为了方便编号从0开始,所以链式前向星必须把h[i]置为-1
2.当(s&-s)>(1<<j)时,即选择的点集合中最小的一个点都比j大时,要continue!!!因为这时s&(1<<j)==0,但是它并不能累加贡献和转移!!!因为这里没考虑到疯狂WA……
3.只有s中包含j而且s的最后一个选择的点恰好是j的时候累加贡献。
4.不开long long 见祖宗
 1 #include<stdio.h>
 2 #define it register int
 3 #define il inline
 4 const int N=1000005;
 5 int n,m,h[N],nxt[N],adj[N],t,u,v,lim;
 6 long long ans,f[20][N];
 7 il void add(){
 8     nxt[++t]=h[u],h[u]=t,adj[t]=v,nxt[++t]=h[v],h[v]=t,adj[t]=u;
 9 }
10 il void fr(int &num){
11     num=0;char c=getchar();int p=1;
12     while(c<'0'||c>'9') c=='-'?p=-1,c=getchar():c=getchar();
13     while(c>='0'&&c<='9') num=num*10+c-'0',c=getchar();
14     num*=p;
15 }  
16 int main(){
17     fr(n),fr(m),lim=1<<n; 
18     for(it i=0;i<n;++i) f[i][1<<i]=1,h[i]=-1;
19     for(it i=1;i<=m;++i) fr(u),fr(v),--u,--v,add();
20     for(it s=1;s<lim;++s)
21         for(it i=0;i<n;++i)
22             if(f[i][s])
23                 for(it tp=h[i],j;~tp;tp=nxt[tp]){
24                     j=adj[tp];
25                     if((s&-s)>(1<<j)) continue;
26                     if((s&(1<<j))) ans+=((s&-s)==(1<<j)?f[i][s]:0);
27                     else f[j][s|(1<<j)]+=f[i][s]; 
28                 }
29     printf("%lld",ans-m>>1);
30     return 0;
31 }
View Code

 

posted @ 2019-10-28 16:18  kylin_xy  阅读(116)  评论(0编辑  收藏  举报