传送门:Poj 2186
题意:给你n头牛,m种关系,A牛认为B牛是popular的,B牛认为C牛是popular的,则A也认为C是popular的,问最终有几头被所有牛认为是popular的牛
题解:强连通缩点基础题(虽然我Tarjan和缩点都是对的,但是最终讨论判断的时候写垮了(写了3天。。。。还不是你懒!!!!过年划水这么多天缩点后找出度为零的点个数。然后讨论是否有这样子的点,如果没有则全都是(整个都是强连通图),如果只有一个,那么那个强连通分量所含的牛的个数就是所求解,如果有多个那么都是不是。
#include<iostream> #include<cstdio> using namespace std; const int N =1e4+5; int head[N]; int nx[N*N]; int to[N*N]; int tot=1; int vis[N]; int comNum; int comMap[N]; int Stack[N]; int Stacksize; int n,m; int dfn[N],low[N]; int indegree[N],outdegree[N]; int Map[N]; void make_list(int u,int v){ to[tot]=v; nx[tot]=head[u]; head[u]=tot++; } void dfs(int u,int step){ dfn[u]=low[u]=step; vis[u]=1; Stack[++Stacksize]=u; for(int i=head[u];i;i=nx[i]){ int v=to[i]; if(vis[v]==0)dfs(v,step+1); if(vis[v]==1)low[u]=min(low[u],low[v]); } if(dfn[u]==low[u]){ comNum++; int sum=0; int k; do{ sum++; k=Stack[Stacksize--]; comMap[k]=comNum; vis[k]=2; }while(k!=u); Map[comNum]=sum; } } void tarjan(){ for(int i=1;i<=n;i++){ if(!vis[i])dfs(i,1); } } int main(){ while(~scanf("%d %d",&n,&m)){ memset(head,0,sizeof(head)); memset(indegree,0,sizeof(indegree)); memset(outdegree,0,sizeof(outdegree)); comNum=Stacksize=0; memset(Map,0,sizeof(Map)); memset(vis,0,sizeof(vis)); for(int i=0;i<m;i++){ int a,b; scanf("%d%d",&a,&b); make_list(a,b); } tarjan(); for(int u=1;u<=n;u++){ for(int i=head[u];i;i=nx[i]){ int v=to[i]; if(comMap[u]!=comMap[v]){ indegree[comMap[v]]++; outdegree[comMap[u]]++; } } } int ans=0; int po=0; for(int i=1;i<=comNum;i++){ if(outdegree[i]==0){ ans+=Map[i]; po++; } } if(po>1)ans=0; printf("%d\n",ans); } return 0; }