• 【HAOI2006】【BZOJ1051】【p1233】最受欢迎的牛


    BZOJ难得的水题(其实是HA太弱了)

    原题:

    每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。 这
    种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少头
    牛被所有的牛认为是受欢迎的。
    N<=10000,M<=50000
     

    求强连通分量,缩点,搞成DAG,唯一一个出度为0的点就是答案

    为什么呐

    缩点后每个强连通块内部肯定是能互相到达的,而且强连通块是DAG没有环,所以如果整个DAG是连通的,那么唯一一个出度为零的强连通块一定会被其他所有强连通块覆盖(因为图是连通的而且没有环)

    (似乎涉及到覆盖问题都可以用缩点搞)

    需要注意的问题:

    1.注意图不一定连通!!!

    2.需要判断DAG是否连通,如果有多个点出度为0,答案就是0,因为这样子就没有任何一个强连通块能被其他所有强连通块覆盖

    画图模拟很好理解

    这题在BZOJ上WA了好几遍,全是低级错误,代码能力还要再提升

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 using namespace std;
     7 int read(){int z=0,mark=1;  char ch=getchar();
     8     while(ch<'0'||ch>'9'){if(ch=='-')mark=-1;  ch=getchar();}
     9     while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0';  ch=getchar();}
    10     return z*mark;
    11 }
    12 struct ddd{int next,y;}e[51000];int LINK[11000],ltop=0;
    13 inline void insert(int x,int y){e[++ltop].next=LINK[x];LINK[x]=ltop;e[ltop].y=y;}
    14 ddd DAG[11000];  int DLINK[51000],Dltop=0;  int Dcd[11000];
    15 inline void Dinsert(int x,int y){DAG[++Dltop].next=DLINK[x];DLINK[x]=Dltop;DAG[Dltop].y=y;  Dcd[x]++;}
    16 int n,m;
    17 int low[11000],dfn[11000],bu=0;
    18 int zhan[1100000],top=0;
    19 bool visited[11000];
    20 int group[11000],id=0;
    21 int ge[11000];
    22 void Tarjian(int x){
    23     zhan[++top]=x;  visited[x]=true;
    24     low[x]=dfn[x]=++bu;
    25     for(int i=LINK[x];i;i=e[i].next){
    26         if(!dfn[e[i].y]){
    27             Tarjian(e[i].y);
    28             low[x]=min(low[x],low[e[i].y]);
    29         }
    30         else if(visited[e[i].y])
    31             low[x]=min(low[x],dfn[e[i].y]);
    32     }
    33     if(dfn[x]==low[x]){
    34         id++;
    35         int temp;
    36         do{
    37             temp=zhan[top--];
    38             visited[temp]=false;
    39             group[temp]=id;
    40             ge[id]++;
    41         }while(temp!=x);
    42     }
    43 }
    44 void get_DAG(){
    45     for(int i=1;i<=n;i++)
    46         for(int j=LINK[i];j;j=e[j].next)
    47             if(group[i]!=group[e[j].y])
    48                 Dinsert(group[i],group[e[j].y]);
    49 }
    50 int main(){//freopen("ddd.in","r",stdin);
    51     memset(visited,0,sizeof(visited));
    52     memset(dfn,0,sizeof(dfn));
    53     memset(ge,0,sizeof(ge));
    54     cin>>n>>m;
    55     int _left,_right;
    56     while(m --> 0){//趋向于
    57         _left=read();  _right=read();
    58         insert(_left,_right);
    59     }
    60     for(int i=1;i<=n;i++)if(!dfn[i])  Tarjian(i);//注意图不一定连通!!!
    61     get_DAG();
    62     int temp=0;
    63     for(int i=1;i<=id;i++)if(Dcd[i]==0){
    64         if(temp){  temp=0;  break;}//防止DAG不连通,这样子就没有任何一个强连通块能被其他所有强连通块覆盖
    65         else  temp=i;
    66     }
    67     cout<<ge[temp]<<endl;
    68     return 0;
    69 }
    View Code
  • 相关阅读:
    第九天 how can I 坚持
    第八天 how can I 坚持
    第七天 how can I 坚持
    第六天 how can I 坚持
    第五天 how can I 坚持
    第四天 how can I 坚持
    第三天 how can I坚持
    第二天 how can I 坚持
    raw文件系统 分类: 生活百科 2013-11-09 14:12 448人阅读 评论(0) 收藏
    初次接触:DirectDraw 分类: VC++ DirectX 2013-11-09 11:16 950人阅读 评论(0) 收藏
  • 原文地址:https://www.cnblogs.com/JSL2018/p/5822080.html
Copyright © 2020-2023  润新知