BZOJ1051(洛谷P2341) [HAOI2006]受欢迎的牛

来源:互联网 发布:plsql输入ip连接数据 编辑:程序博客网 时间:2024/06/05 11:40

缩点

BZOJ传送门

洛谷传送门

Tarjan缩点,出度为0的点的数目即为答案。

注意可能有多个连通块(BZOJ数据没有)

代码:

#include<cstdio>#include<cstring>#include<algorithm>#define MAXN 10000#define MAXM 50000using namespace std;struct edge{    int next,to;};int n,m,k,top,p,sum;int h[MAXN+5],num[MAXN+5];int low[MAXN+5],dfn[MAXN+5],stack[MAXN+5];edge ed[MAXM+5];bool f[MAXN+5],vis[MAXN+5];void Tarjan(int x){    dfn[x]=low[x]=++p;    stack[++top]=x; f[x]=true;    for (int i=h[x];i;i=ed[i].next)        if (!dfn[ed[i].to]){            Tarjan(ed[i].to);            low[x]=min(low[x],low[ed[i].to]);        }        else if (f[ed[i].to]) low[x]=min(low[x],dfn[ed[i].to]);    if (low[x]==dfn[x]){        f[x]=false;        while (stack[top+1]!=x){            num[stack[top]]=x;            f[stack[top--]]=false;        }    }}void addedge(int x,int y){    ed[++k].next=h[x]; ed[k].to=y; h[x]=k;}int main(){    scanf("%d%d",&n,&m);    for (int i=1;i<=m;i++){        int u,v;        scanf("%d%d",&u,&v);        addedge(u,v);    }    for (int i=1;i<=n;i++)        if (!dfn[i]) Tarjan(i);    for (int i=1;i<=n;i++)        for (int j=h[i];j;j=ed[j].next)            if (num[i]!=num[ed[j].to])                f[num[i]]=true;    int ans=0;    for (int i=1;i<=n;i++){        if (!f[num[i]]){            if (!vis[num[i]]){                sum++;                vis[num[i]]=true;            }            ans++;        }    }    if (sum>1) printf("0\n");    else printf("%d\n",ans);    return 0;}
原创粉丝点击