首页 写随笔

cdcq

现用博客:https://www.cnblogs.com/cdcq/

My Links

Blog Stats

【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

 

posted on 2016-08-30 15:01  cdcq_old  阅读(...)  评论(... 编辑 收藏