CF505D Mr. Kitayuta's Technology 题解

首先会发现一个规律:对于任意一个连通块,当连通块内有环时,这个连通块对答案的贡献为连通块内点数,没有环时贡献为点数-1

所以,我们对于每一个点,用dfs求出它所在的连通块跑拓扑排序判环,再根据上面的结论求出答案

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<vector>
 4 using namespace std;
 5 vector<int> pie;
 6 int n,m,t,t2,h[200005],h2[200005],ans,in[100005],q[100005];
 7 struct E{int to,next;}g[200005],g2[100005];
 8 void ins(int u,int v){g[++t].to=v,g[t].next=h[u],h[u]=t;}
 9 void ins2(int u,int v){g2[++t2].to=v,g2[t2].next=h2[u],h2[u]=t2;}
10 bool pvis[100005],flag;
11 void dfs(int u){
12     pvis[u]=1; pie.push_back(u);
13     for(int i=h[u];i;i=g[i].next){
14         int v=g[i].to;
15         if(!pvis[v]) dfs(v);
16     }
17 }
18 bool tp(){
19     int num=pie.size(),head=0,tail=0;
20     for(int i=0;i<num;++i){
21         int u=pie[i];
22         for(int j=h2[u];j;j=g2[j].next)
23             in[g2[j].to]++;
24     }
25     for(int i=0;i<num;++i){
26         int u=pie[i];
27         if(!in[u]) q[++tail]=u;
28     }
29     if(tail==0) return 0;
30     while(head<tail){
31         int u=q[++head];
32         if(!h2[u]) continue;
33         for(int i=h2[u];i;i=g2[i].next){
34             int v=g2[i].to;
35             in[v]--;
36             if(!in[v]) q[++tail]=v;
37         }
38     }
39     if(tail<num) return 0;
40     return 1;
41 }
42 int main(){
43     scanf("%d%d",&n,&m); ans=n;
44     for(int i=1;i<=m;++i){
45         int u,v;
46         scanf("%d%d",&u,&v);
47         ins(u,v); ins(v,u);
48         ins2(u,v);
49     }
50     for(int i=1;i<=n;++i){
51         if(pvis[i]) continue;
52         pie.clear();
53         dfs(i);
54         ans-=tp();
55     }
56     printf("%d\n",ans);
57 }
View Code

猜你喜欢

转载自www.cnblogs.com/xie-dodo/p/8964596.html