[破碎的状态] BZOJ 1051
不能说是我水平厉害了吧
只是以前做过的题还是有点熟练的..
1A
算法:scc一遍
然后求哪些点没出度然后就行了
代码:
#include<set> #include<map> #include<list> #include<queue> #include<stack> #include<math.h> #include<string> #include<time.h> #include<bitset> #include<vector> #include<memory> #include<utility> #include<stdio.h> #include<sstream> #include<fstream> #include<iostream> #include<stdlib.h> #include<string.h> #include<algorithm> using namespace std; struct edge { int y; edge * next; }; edge * li[100005]; edge * new_edge() { static edge a[100005]; static int top=0; return &a[top++]; } void insert_edge(int x,int y) { edge * t=new_edge(); t->y=y; t->next=li[x]; li[x]=t; } int dfn[100005],low[100005]; int belong_to[100005]; bool inque[100005]; int tot; void scc(int x) { static int num=0; static int que[100005]; dfn[x]=num; low[x]=num; num++; static int now=0; que[now++]=x; inque[x]=true; edge * t; for (t=li[x];t!=0;t=t->next) { if (dfn[t->y]==-1) { scc(t->y); low[x]=min(low[t->y],low[x]); } else if (inque[t->y]) { low[x]=min(dfn[t->y],low[x]); } } if (dfn[x]==low[x]) { for (;;) { now--; int t=que[now]; inque[t]=false; belong_to[t]=tot; if (que[now]==x) { break; } } tot++; } } bool cannot[100005]; int main() { #ifdef absi2011 freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); #endif int n,m; scanf("%d%d",&n,&m); int i; for (i=0;i<m;i++) { int x,y; scanf("%d%d",&x,&y); x--; y--; insert_edge(x,y); } memset(dfn,-1,sizeof(dfn)); for (i=0;i<n;i++) { if (dfn[i]==-1) scc(i); } for (i=0;i<n;i++) { edge * t; for (t=li[i];t!=0;t=t->next) { if (belong_to[i]!=belong_to[t->y]) { cannot[belong_to[i]]=true; break; } } } int onlyans=-2; for (i=0;i<tot;i++) { if (!cannot[i]) { if (onlyans!=-2) { onlyans=-1; } else { onlyans=i; } } } if (onlyans==-1) { puts("0"); return 0; } int sum=0; for (i=0;i<n;i++) { if (onlyans==belong_to[i]) { sum++; } } printf("%d\n",sum); return 0; }