题目分析:
考虑一个源点集合$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 }