标签:
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 30680 | Accepted: 12445 |
Description
Input
Output
Sample Input
3 3 1 2 2 1 2 3
Sample Output
1
大意:n只牛,m对数(a,b)表示a认为b牛逼。若a认为b牛逼,b认为c牛逼,那么a也认为c牛逼。问n只牛中,有多少只牛是其他所有牛都认为牛逼的。
分析:若图为不连通,则答案为0.当图连通时,在同一个强连通分量A中的牛在被该强连通分量中其他牛认为牛逼;若在A和另一个强连通分量B之间有路,假设A指向B,则A中的牛都认为B中的牛是牛逼的。任意一个有向图都可以分解成若干不相交的强连通分量,把每个强连通分量缩点,就得到一个DAG(有向无环图)。该题要找的是缩点后DAG中出度为0的点所表示的强连通分量中的点数。(该出度为0的点一定唯一,否则不可能有其他牛都认为牛逼的牛)
求强连通分量可使用tarjan算法。
void tarjan(int s) { vis[s]=2; dfn[s]=low[s]=++now; sta.push(s); for(int i=0; i<gra[s].size(); i++) { int t=gra[s][i]; if(dfn[t]==0) { tarjan(t); low[s]=min(low[s],low[t]); } else if(vis[t]==2) low[s]=min(low[s],dfn[t]); } if(low[s]==dfn[s]) { sum++; while(!sta.empty()) { int t=sta.top(); sta.pop(); vis[t]=1; num[t]=sum; if(t==s) break; } } }
AC代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<stdlib.h> #include<vector> #include<stack> using namespace std; #define LL long long #define N 10005 vector<int> gra[N]; stack<int>sta; int n,m,dfn[N],low[N],vis[N],num[N]; int degree[N],sum,now,res,loc; void init() { sum=0; now=0; res=0; memset(vis,0,sizeof(vis)); memset(low,0,sizeof(low)); memset(dfn,0,sizeof(dfn)); memset(degree,0,sizeof(degree)); for(int i=0; i<=n; i++) gra[i].clear(); while(!sta.empty()) sta.pop(); } void read() { int a,b; scanf("%d%d",&n,&m); for(int i=0; i<m; i++) { scanf("%d%d",&a,&b); gra[a].push_back(b); } } void tarjan(int s) { vis[s]=2; dfn[s]=low[s]=++now; sta.push(s); for(int i=0; i<gra[s].size(); i++) { int t=gra[s][i]; if(dfn[t]==0) { tarjan(t); low[s]=min(low[s],low[t]); } else if(vis[t]==2) low[s]=min(low[s],dfn[t]); } if(low[s]==dfn[s]) { sum++; while(!sta.empty()) { int t=sta.top(); sta.pop(); vis[t]=1; num[t]=sum; //缩点 if(t==s) break; } } } void solve() { for(int i=1; i<=n; i++) if(!dfn[i]) tarjan(i); for(int i=1; i<=n; i++) for(int j=0; j<gra[i].size(); j++) if(num[i]!=num[gra[i][j]]) degree[num[i]]++; //对缩点后的DAG进行出度的统计 for(int i=1; i<=sum; i++) { if(degree[i]==0) { res++; loc=i; //第几个强连通分量 } } if(res>1) printf("0\n"); else { res=0; for(int i=1; i<=n; i++) if(num[i]==loc) res++; printf("%d\n",res); } } int main() { init(); read(); solve(); return 0; } /* 3 3 1 2 2 1 2 3 */
标签:
原文地址:http://www.cnblogs.com/jasonlixuetao/p/5793538.html