bzoj1051 受欢迎的牛 结论+tarjan

来源:互联网 发布:.top域名为什么便宜 编辑:程序博客网 时间:2024/06/07 04:06

首先按dfs的思路就是枚举所有牛,然后再枚举所有牛,看能不能到达

但这个题做法比较特殊,不是从暴力优化的角度推得出的

需要从 对单个牛的角度转变为 对所有牛的角度入手

如果答案是多只牛,那这多只牛一定是可以互达的

所以就可以缩环,然后如果有点出度为0,由于缩过环,所以不可能再回来

然后就是扫一遍统计答案+判断了


码:

#include<iostream>#include<cstdio>#include<cstring>using namespace std;#define N 10005#define M 50005int tot,zhong[M],zhong2[M],hou[M],hou2[M],xia[N],xia2[N],up[N],jh[N],jhs,gs[N],dfn[N],top,sta[N],n,m,i,j,ans,st,a,b;void jia(int a,int b){++tot,zhong[tot]=b,hou[tot]=xia[a],xia[a]=tot;}void jia2(int a,int b){++tot,zhong2[tot]=b,hou2[tot]=xia2[a],xia2[a]=tot;}void tarjan(int o){//cout<<o;dfn[o]=up[o]=++tot;int i;sta[++top]=o;for(i=xia[o];i!=-1;i=hou[i]){int nd=zhong[i];if(dfn[nd]==0){tarjan(nd);up[o]=min(up[o],up[nd]);}else{if(jh[nd]!=0)continue;up[o]=min(up[o],up[nd]);}}if(dfn[o]==up[o]){++jhs;while(sta[top]!=o){jh[sta[top]]=jhs;gs[jhs]++;top--;}jh[sta[top]]=jhs;gs[jhs]++;top--;}}int main(){memset(xia,-1,sizeof(xia));memset(xia2,-1,sizeof(xia2));scanf("%d%d",&n,&m);for(i=1;i<=m;i++){scanf("%d%d",&a,&b);jia(a,b);}tot=0;   for(i=1;i<=n;i++)if(dfn[i]==0)tarjan(i);tot=0;   for(i=1;i<=n;i++)   {   st=jh[i];   for(j=xia[i];j!=-1;j=hou[j])   {   int nd=jh[zhong[j]];   if(nd==st)continue;   jia2(st,nd);   }   } // cout<<jhs;for(i=1;i<=jhs;i++){if(xia2[i]==-1){if(ans!=0){printf("0");return 0;}ans=gs[i];}}printf("%d",ans);}


原创粉丝点击