【模板】Tarjan缩点,强连通分量 洛谷P2341 [HAOI2006]受欢迎的牛 [2017年6月计划 强连通分量01]
2017-06-08 18:00
453 查看
P2341 [HAOI2006]受欢迎的牛
题目描述
每头奶牛都梦想成为牛棚里的明星。被所有奶牛喜欢的奶牛就是一头明星奶牛。所有奶牛都是自恋狂,每头奶牛总是喜欢自己的。奶牛之间的“喜欢”是可以传递的——如果A喜
欢B,B喜欢C,那么A也喜欢C。牛栏里共有N 头奶牛,给定一些奶牛之间的爱慕关系,请你
算出有多少头奶牛可以当明星。
输入输出格式
输入格式: 第一行:两个用空格分开的整数:N和M
第二行到第M + 1行:每行两个用空格分开的整数:A和B,表示A喜欢B
输出格式:
第一行:单独一个整数,表示明星奶牛的数量
输入输出样例
输入样例#1:3 3 1 2 2 1 2 3
输出样例#1:
1
说明
只有 3 号奶牛可以做明星【数据范围】
10%的数据N<=20, M<=50
30%的数据N<=1000,M<=20000
70%的数据N<=5000,M<=50000
100%的数据N<=10000,M<=50000
模板题,出度为零的点有且仅有一个才有解,解即为该点内的点数。
#include <bits/stdc++.h> const int INF = 0x3f3f3f3f; const int MAXN = 10000 + 10; const int MAXM = 50000 + 10; inline int read(int &x){ x = 0;char ch = getchar();char c = ch; while(ch > '9' || ch < '0')c = ch, ch = getchar(); while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0',ch = getchar(); if(c == '-') x = -x; } inline int min(int a,int b){return a > b? b : a;} int n,m,tmp1,tmp2,cnt,cnt2,head[MAXN],head2[MAXN]; int dfn[MAXN],low[MAXN], group, num[MAXN],belong[MAXN], t, stack[MAXN], top; bool b[MAXN],bb[MAXN]; struct Edge{int u,v,next;}edge[MAXM],edge2[MAXM]; void insert(int a,int b){edge[++cnt] = Edge{a, b, head[a]};head[a] = cnt;} void insert2(int a,int b){edge2[++cnt2] = Edge{a, b, head2[a]};head2[a] = cnt2;} void dfs(int u){ int now = -1; b[u] = true;bb[u] = true; dfn[u] = low[u] = ++t; stack[++top] = u; for(int pos = head[u];pos;pos = edge[pos].next){ int v = edge[pos].v; if(!b[v]){ dfs(v); if(low[u] > low[v])low[u] = low[v]; } else if(bb[v] && low[u] > dfn[v]){ low[u] = dfn[v]; } } if(low[u] == dfn[u]){ group ++; while(now != u){ now = stack[top --]; bb[now] = false; belong[now] = group; num[group] ++; } } } inline void rebuild(){ for(int u = 1;u <= n;u ++){ for(int pos = head[u];pos;pos = edge[pos].next){ int v = edge[pos].v; if(belong[u] != belong[v]){ insert2(belong[u], belong[v]); } } } } inline void tarjan(){ for(int i = 1;i <= n;i ++)if(!b[i])dfs(i); rebuild(); } int ans; int main(){ read(n);read(m); for(int i = 1;i <= m;i ++){ read(tmp1);read(tmp2);insert(tmp1, tmp2); } tarjan(); for(int i = 1;i <= group;i ++){ if(!head2[i]){ if(ans) ans = 0;break; else ans = num[i]; } } printf("%d", ans); return 0; }
相关文章推荐
- BZOJ 1051: [HAOI2006]受欢迎的牛 强连通分量,Tarjan缩点
- 【bzoj1051】 [HAOI2006]受欢迎的牛 tarjan缩点判出度算点数
- BZOJ[1051][HAOI2006]受欢迎的牛 Tarjan缩点
- 【题解】 [HAOI2006]受欢迎的牛(强连通分量 tarjan)
- [HAOI2006]受欢迎的牛(缩点+Tarjan)
- 【bzoj 1051】[HAOI2006]受欢迎的牛(Tarjan缩点)
- bzoj1051 [HAOI2006]受欢迎的牛(tarjan求强连通分量)
- bzoj1051: [HAOI2006]受欢迎的牛(tarjan强连通分量)
- 【强联通分量缩点】【Tarjan】bzoj1051 [HAOI2006]受欢迎的牛
- [BZOJ 1051][HAOI 2006]受欢迎的牛(tarjan缩点)
- [BZOJ1051][HAOI2006]受欢迎的牛(Tarjan缩点)
- bzoj 1051: [HAOI2006]受欢迎的牛 tarjan缩点
- bzoj1051 [HAOI2006]受欢迎的牛[图论][tarjan缩点]
- bzoj 1051: [HAOI2006]受欢迎的牛(tarjan 缩点)
- [HAOI2006]受欢迎的牛(tarjan缩点)
- [HAOI2006]受欢迎的牛 Tarjan缩点
- BZOJ1051: [HAOI2006]受欢迎的牛(强连通Tarjan 缩点)
- [BZOJ1051] [HAOI2006] 受欢迎的牛 - tarjan强连通分量
- 【Tarjan】BZOJ1051(HAOI2006)[受欢迎的牛]题解
- [bzoj1051] [HAOI2006]受欢迎的牛 (Tarjan+缩点)