BZOJ1051 [HAOI2006]受欢迎的牛(Tarjan缩点)
题意:
在一个有向图中,求一个点集的大小,这个点集里所有的点都由图中的其他点到达
思路:
这个点集一定是一个强连通分量
先对有向图进行缩点变成DAG,DAG中出度为0的点如果只有一个,那答案就是这个,否则没有答案
/************************************************************** Problem: 1051 User: wrjlinkkkkkk Language: C++ Result: Accepted Time:116 ms Memory:2724 kb ****************************************************************/ #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<string> //#include<stack> #include<queue> #include<deque> #include<set> #include<vector> #include<map> #include<functional> #define fst first #define sc second #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) #define lson l,mid,root<<1 #define rson mid+1,r,root<<1|1 #define lc root<<1 #define rc root<<1|1 #define lowbit(x) ((x)&(-x)) using namespace std; typedef double db; typedef long double ldb; typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> PI; typedef pair<ll,ll> PLL; const db eps = 1e-6; const int mod = 100003; const int maxn = 2e5+100; const int maxm = 2e5+100; const ll inf = 0x3f3f3f3f3f3f3f3f; const db pi = acos(-1.0); int color[10010],dfn[20020],low[20020],stack[20020],vis[10010],cnt[10010]; int top,n,m,sum,ans; int deep = 0; vector<int>g[10010]; vector<int>rg[10010]; void tarjan(int u){ dfn[u]=++deep; low[u]=deep; vis[u]=1; stack[++top]=u; int sz=g[u].size(); for(int i=0;i<sz;i++){ int v=g[u][i]; if(!dfn[v]){ tarjan(v); low[u]=min(low[u],low[v]); } else{ if(vis[v]){ low[u]=min(low[u],low[v]); } } } if(dfn[u]==low[u]){ color[u]=++sum; vis[u]=0; while(stack[top]!=u){ color[stack[top]]=sum; vis[stack[top--]]=0; } top--; } return; } int res = 0; int num[10010]; void rb(){ for(int i = 1; i <= n; i++){ num[color[i]]++; int sz = g[i].size(); for(int j = 0; j < sz; j++){ int u = g[i][j]; if(color[i]!=color[u]){ rg[color[i]].pb(color[u]); } } } int flg = 0; for(int i = 1; i <= sum; i++){ //printf("%d %d\n", i, rg[i].size()); if(rg[i].size()==0){ if(flg==0)flg = i; else flg = -1; } } if(flg==-1)flg = 0; else flg = num[flg]; printf("%d", flg); } int main() { sum = 0; mem(num, 0); scanf("%d %d", &n, &m); for(int i = 1; i <= m; i++){ int from, to; scanf("%d %d", &from, &to); g[from].pb(to); } for(int i = 1; i <= n; i++){ if(!dfn[i])tarjan(i); } //for(int i = 1; i <= n; i++)printf("%d %d\n",i, color[i] ); //printf("%d\n", sum); rb(); return 0; }