「CF506B」Mr. Kitayuta’s Technology
结论题TAT
一个弱连通块中没有环的话那么对答案的贡献就是该连通块中点数-1
否则为点的个数
缩环后用并查集维护一下即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
#include<iostream> #include<set> #include<map> #include<cstdio> #include<cstring> #include<cstdlib> #include<ctime> #include<vector> #include<queue> #include<algorithm> #include<cmath> #include<bitset> #define inf 2000000000 #define pa pair<int,int> #define ll long long using namespace std; ll read() { ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n,m,ans,cnt,ind,top,scc; int low[100005],dfn[100005],q[100005],bl[100005],num[100005]; int fa[100005],last[100005]; bool inq[100005],mark[100005]; struct edge{ int to,next,v; }e[100005]; void insert(int u,int v) { e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt; } int find(int x) { return x==fa[x]?x:fa[x]=find(fa[x]); } void tarjan(int x) { low[x]=dfn[x]=++ind; inq[x]=1;q[++top]=x; for(int i=last[x];i;i=e[i].next) if(!dfn[e[i].to]) { tarjan(e[i].to); low[x]=min(low[x],low[e[i].to]); } else if(inq[e[i].to]) low[x]=min(low[x],dfn[e[i].to]); if(low[x]==dfn[x]) { int now=0;scc++; while(x!=now) { now=q[top];top--; bl[now]=scc; inq[now]=0; num[scc]++; if(num[scc]!=1)mark[scc]=1; } } } void rebuild() { cnt=0; for(int x=1;x<=n;x++) { for(int i=last[x];i;i=e[i].next) { int u=bl[x],v=bl[e[i].to]; int p=find(u),q=find(v); if(p!=q) { fa[p]=q;num[q]+=num[p];mark[q]|=mark[p]; } } } } int main() { n=read();m=read(); for(int i=1;i<=m;i++) { int u=read(),v=read(); insert(u,v); } for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i); for(int i=1;i<=scc;i++)fa[i]=i; rebuild(); for(int i=1;i<=scc;i++) if(fa[i]==i) { if(!mark[i])ans+=num[i]-1; else ans+=num[i]; } printf("%d\n",ans); return 0; } |
Subscribe