Codeforces1036G Sources and Sinks 【构造】【状态压缩】

题目分析:

考虑一个源点集合$S$,如果$S$能到的点$T$比$S$小,那么$T$全连到$S$里面,其它点就到不了$T$啦。否则我们全连完后$S$集合被迫扩大,所以总能扩大满。

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn = 1002000;
 5 
 6 int n,m,in[maxn],f[maxn],nb[maxn],Num;
 7 vector <int> g[maxn];
 8 int forw[maxn],flag;
 9 
10 void dfs(int now){
11     if(g[now].size() == 0) f[now] = (1<<nb[now]-1);
12     for(int i=0;i<g[now].size();i++){
13     if(!f[g[now][i]]) dfs(g[now][i]);
14     f[now] |= f[g[now][i]];
15     }
16 }
17 
18 void read(){
19     scanf("%d%d",&n,&m);
20     for(int i=1;i<=m;i++){
21     int u,v; scanf("%d%d",&u,&v);
22     g[u].push_back(v);
23     in[v] ++;
24     }
25     for(int i=1;i<=n;i++) if(!g[i].size()) nb[i] = ++Num;
26     Num = 0;
27     for(int i=1;i<=n;i++) if(!in[i]) dfs(i),forw[++Num]=f[i];
28 }
29 
30 void dfs(int now,int cho,int dt){
31     if(now > Num){
32     if(cho == Num) return;
33     if(cho == 0) return;
34     if(__builtin_popcount(dt) <= cho)flag = 1;
35     }else{
36     dfs(now+1,cho,dt);
37     dfs(now+1,cho+1,dt|forw[now]);
38     }
39 }
40 
41 void work(){
42     dfs(1,0,0);
43     if(flag){puts("NO");}
44     else puts("YES");
45 }
46 
47 int main(){
48     read();
49     work();
50     return 0;
51 }

 

posted @ 2018-09-11 11:15  menhera  阅读(337)  评论(0编辑  收藏  举报