受欢迎的牛 [HAOI2006] [强连通] [传递闭包(划)]

Description

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

Input

第1行两个整数N,M;
接下来M行,每行两个数A,B,意思是A认为B是受欢迎的(给出的信息有可能重复,即有可能出现多个A,B)

Output

一个数,即有多少头牛被所有的牛认为是受欢迎的。

Sample Input

3 3

1 2

2 1

2 3

Sample Output

1

Hint

10%的数据N<=20,M<=50
30%的数据N<=1000,M<=20000
70%的数据N<=5000,M<=50000
100%的数据N<=10000,M<=50000

Solution

首先,如果数据很小的话可以用传递闭包对吧,但是N到了1e5就显然不行了。

显然如果在一个环里的各个点的传递是互达的,由此我们可以扩展到一个强连通分量也是这样。

于是我们就可以想到tarjan缩点。

缩完点后怎么办呢?愚蠢的我想到一个点的入度=点数-1就对答案产生贡献,显然是不对的(如 3->2->1)。

于是我第一遍只有70分,(这样都有70分可能是数据太水了)。

脑子不好使的我冒着被卡的风险在缩完点后使用传递闭包(不要问我为什么我这么喜欢传递闭包),居然过了!(可能是数据太水了)

然后我便看正解,发现果然还是大佬们聪明一点。

对于缩完点后的点x

i)如果出度!=0,那么肯定有没指向自己的点,(如果有指出去后又指回来肯定在连通分量内)

ii)如果出度==0,似乎这个连通分量内的点就是答案,但是如果有多个出度为0的点,就说明还有多个独立的区域,那也不行。

     所以出度==0的点有且只有一个的时候即为答案

 

Code (传递闭包版)

 

 1 #include<set>
 2 #include<stack>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<iostream>
 6 #include<algorithm>
 7 #define RG register int
 8 #define rep(i,a,b)    for(RG i=a;i<=b;i++)
 9 #define per(i,a,b)    for(RG i=a;i>=b;i--)
10 #define inf (1<<30)
11 #define maxn 10005
12 #define maxm 500005
13 #define add(x,y) e[++cnt].u=u,e[cnt].v=v,e[cnt].next=head[u],head[u]=cnt
14 using namespace std;
15 stack<int> stk;
16 set<int> st[maxn];
17 int n,m,cnt,id,sid,ans;
18 int head[maxn],scc[maxn],dfn[maxn],low[maxn],vis[maxn],ind[maxn],sz[maxn],oud[maxn];
19 int gra[1000][1000];
20 struct E{
21     int u,v,next;
22 }e[maxm];
23 inline int read()
24 {
25     int x=0,f=1;char c=getchar();
26     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
27     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
28     return x*f;
29 }
30 
31 void tarjan(int u,int fa)
32 {
33     low[u]=dfn[u]=++id;
34     stk.push(u);vis[u]=1;
35     for(int i=head[u];i;i=e[i].next)
36     {
37         int v=e[i].v;
38         if(!dfn[v])
39         {
40             tarjan(v,u);low[u]=min(low[u],low[v]);
41         }
42         else if(vis[v])    low[u]=min(low[u],dfn[v]);
43     }
44     if(low[u]==dfn[u])
45     {
46         ++sid;int x;
47         do{
48             x=stk.top(),stk.pop();
49             vis[x]=0,scc[x]=sid,sz[sid]++;
50         }while(x!=u);
51     }
52 }
53 
54 
55 
56 int main()
57 {
58     n=read(),m=read();
59     RG u,v;rep(i,1,m) u=read(),v=read(),add(u,v);
60     rep(i,1,n)    if(!scc[i])    tarjan(i,0);
61     rep(i,1,cnt)
62     {
63         int x=scc[e[i].u],y=scc[e[i].v];
64         if(x!=y)
65             gra[x][y]=1;
66     }
67     rep(k,1,sid)
68         rep(i,1,sid)
69             rep(j,1,sid)
70                 if(gra[i][k]&&gra[k][j])gra[i][j]=1;
71     rep(i,1,sid)
72     {
73         int flg=0;
74         rep(j,1,sid)
75             if(i!=j&&!gra[j][i]) flg=1;
76         if(!flg) ans+=sz[i];
77     }
78     cout<<ans;
79     return 0;
80 }
>>点击查看代码<<

 

 

 

 1 #include<set>
 2 #include<stack>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<iostream>
 6 #include<algorithm>
 7 #define RG register int
 8 #define rep(i,a,b)    for(RG i=a;i<=b;i++)
 9 #define per(i,a,b)    for(RG i=a;i>=b;i--)
10 #define inf (1<<30)
11 #define maxn 10005
12 #define maxm 500005
13 #define add(x,y) e[++cnt].u=u,e[cnt].v=v,e[cnt].next=head[u],head[u]=cnt
14 using namespace std;
15 stack<int> stk;
16 set<int> st[maxn];
17 int n,m,cnt,ccnt,id,sid,ans;
18 int head[maxn],hh[maxn],scc[maxn],dfn[maxn],low[maxn],vis[maxn],ind[maxn],sz[maxn],oud[maxn];
19 int gra[1000][1000];
20 struct E{
21     int u,v,next;
22 }e[maxm];
23 struct EE{
24     int v,next;
25 }edge[maxm];
26 inline int read()
27 {
28     int x=0,f=1;char c=getchar();
29     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
30     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
31     return x*f;
32 }
33 
34 void tarjan(int u,int fa)
35 {
36     low[u]=dfn[u]=++id;
37     stk.push(u);vis[u]=1;
38     for(int i=head[u];i;i=e[i].next)
39     {
40         int v=e[i].v;
41         if(!dfn[v])
42         {
43             tarjan(v,u);low[u]=min(low[u],low[v]);
44         }
45         else if(vis[v])    low[u]=min(low[u],dfn[v]);
46     }
47     if(low[u]==dfn[u])
48     {
49         ++sid;int x;
50         do{
51             x=stk.top(),stk.pop();
52             vis[x]=0,scc[x]=sid,sz[sid]++;
53         }while(x!=u);
54     }
55 }
56 
57 
58 
59 int main()
60 {
61     n=read(),m=read();
62     RG u,v;rep(i,1,m) u=read(),v=read(),add(u,v);
63     rep(i,1,n)    if(!scc[i])    tarjan(i,0);
64     rep(i,1,cnt)
65     {
66         int x=scc[e[i].u],y=scc[e[i].v];
67         if(x!=y)
68             gra[x][y]=1;
69     }
70     rep(k,1,sid)
71         rep(i,1,sid)
72             rep(j,1,sid)
73                 if(gra[i][k]&&gra[k][j])gra[i][j]=1;
74     rep(i,1,sid)
75     {
76         int flg=0;
77         rep(j,1,sid)
78             if(i!=j&&!gra[j][i]) flg=1;
79         if(!flg) ans+=sz[i];
80     }
81     cout<<ans;
82     return 0;
posted @ 2018-04-03 19:41  iBilllee  阅读(243)  评论(0编辑  收藏  举报