Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 19647 | Accepted: 7960 |
Description
Input
Output
Sample Input
3 3 1 2 2 1 2 3
Sample Output
1
Hint
Source
题目大意:给一张图,求所有点可达的点的个数。
题目分析:先求一次强连通将有环图转化成一个DAG,然后缩点,求新图中出度为0的点的个数,如果出度为0的点只有1个则这个强连通所有点都能被其他点可达,否则没有点能被所有点可达。
详情请见代码:
#include <iostream> #include<cstdio> #include<cstring> using namespace std; const int N = 10005; const int M = 50005; struct edge { int to,next; }g[M]; int head[N]; int scc[N]; int cnt[N];//统计强连通的点数 int stack1[N]; int stack2[N]; int vis[N]; int out[N]; int m,n; void init() { int i; for(i = 1;i <= n;i ++) { head[i] = -1; scc[i] = cnt[i] = vis[i] = out[i] = 0; } } int nextint() { char c; int ret; while((c = getchar()) > '9' || c < '0') ; ret = c - '0'; while((c = getchar()) >= '0' && c <= '9') ret = ret * 10 + c - '0'; return ret; } void dfs(int cur,int &sig,int &ret) { vis[cur] = ++sig; stack1[++stack1[0]] = cur; stack2[++stack2[0]] = cur; for(int i = head[cur];i != -1;i = g[i].next) { if(vis[g[i].to] == 0) dfs(g[i].to,sig,ret); else if(scc[g[i].to] == 0) { while(vis[stack2[stack2[0]]] > vis[g[i].to]) stack2[0] --; } } if(stack2[stack2[0]] == cur) { ++ret; stack2[0] --; do { scc[stack1[stack1[0]]] = ret; cnt[ret] ++; }while(stack1[stack1[0] --] != cur); } } int Gabow() { int i,sig,ret; stack1[0] = stack2[0] = sig = ret = 0; for(i = 1;i <= n;i ++) if(!vis[i]) dfs(i,sig,ret); return ret; } int solve() { int ret,i,j; int num = Gabow(); if(num == 1) return n; for(i = 1;i <= n;i ++) { for(j = head[i];j != -1;j = g[j].next) { if(scc[i] != scc[g[j].to]) out[scc[i]] ++; } } int ct = 0; int ci; for(i = 1;i <= num;i ++) { if(out[i] == 0) { ct ++; ci = i; } } if(ct == 1) return cnt[ci]; else return 0; } int main() { int i,j,a,b; while(~scanf("%d%d",&n,&m)) { init(); for(i = 1;i <= m;i ++) { a = nextint(); b = nextint(); g[i].to = b; g[i].next = head[a]; head[a] = i; } printf("%d\n",solve()); } return 0; } //1468K 16MS G++ //824K 110MS C++