受欢迎的牛 tarjan求scc模板

第一遍不太熟,第二遍飞快地打出来了

算是tarjan模板了吧,几天了也总算是有一点对tarjan求法过程的理解了。

if(!dfn[u])tarjan(u),low[x] = min(low[x],low[u]);//如果没有访问过u,则tarjan一下,如果u走出去搞到的low更小则用这个更新x的low

else if(ins[u])low[x] = min(low[x],dfn[u]);//如果u访问过但在栈里,那么u的low说不定已经被更新过了,如果此时令low[x]与low[u]取min,则回溯时作为祖先的u的low与dfn就不相等了欸在这道题里好像确实是等价的,可能在其他tarjan算法里不等价吧,那我还是不太知道为什么在这里与dfn[u]取min了。。。whatsapity..

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<vector>
 6 #include<queue>
 7
 8 using namespace std;
 9
10 const int Maxn = 10010;
11
12 vector<int> g[Maxn],scc[Maxn];
13 int stack[Maxn],ins[Maxn],inscc[Maxn];
14 int dfn[Maxn],low[Maxn],oud[Maxn];
15 int n,m,cntv,cntscc,top;
16
17 void tarjan(int x){
18     low[x] = dfn[x] = ++cntv;
19     ins[x] = 1,stack[++top] = x;
20     for(int i = 0;i < g[x].size();i++){
21         int u = g[x][i];
22         if(!dfn[u])tarjan(u),low[x] = min(low[x],low[u]);
23         else if(ins[u])low[x] = min(low[x],dfn[u]);
24     }
25     if(dfn[x] == low[x]){
26         int y = 0; cntscc++;
27         while(y != x){
28             y = stack[top--];
29             ins[y] = 0;
30             inscc[y] = cntscc;
31             scc[cntscc].push_back(y);
32         }
33     }
34 }
35
36 int main(){
37     ios::sync_with_stdio(false);
38     cin >> n >> m;
39     for(int i = 1;i <= m;i++){
40         int x,y;
41         cin >> x >> y;
42         g[x].push_back(y);
43     }
44     for(int i = 1;i <= n;i++)if(!dfn[i])tarjan(i);
45     for(int i = 1;i <= cntscc;i++){
46         for(int j = 0;j < scc[i].size();j++){
47             int u = scc[i][j];
48             for(int k = 0;k < g[u].size();k++){
49                 int v = g[u][k];
50                 if(inscc[v] != i)oud[i]++;
51             }
52         }
53     }
54     int ans = 0;
55     for(int i = 1;i <= cntscc;i++)if(!oud[i]){
56         if(ans){printf("0");return 0;}
57         ans = scc[i].size();
58     }
59     cout << ans;
60 return 0;
61 }

原文地址:https://www.cnblogs.com/Wangsheng5/p/11651417.html

时间: 2024-10-10 18:12:49

受欢迎的牛 tarjan求scc模板的相关文章

【BZOJ1051】1051: [HAOI2006]受欢迎的牛 tarjan求强连通分量+缩点

Description 每一头牛的愿望就是变成一头最受欢迎的牛.现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎. 这种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎.你的任务是求出有多少头牛被所有的牛认为是受欢迎的. Input 第一行两个数N,M. 接下来M行,每行两个数A,B,意思是A认为B是受欢迎的(给出的信息有可能重复,即有可能出现多个A,B) Output 一个数,即有多少头牛被所有的牛认为是受欢迎的. Sample Input 3 3

poj2186 最受欢迎的牛(求最受欢迎的牛的数量)

Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 27531   Accepted: 11077 Description Every cow's dream is to become the most popular cow in the herd. In a herd of N (1 <= N <= 10,000) cows, you are given up to M (1 <= M &

bzoj 1051: [HAOI2006]受欢迎的牛 tarjan缩点

1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2092  Solved: 1096[Submit][Status] Description 每一头牛的愿望就是变成一头最受欢迎的牛.现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎. 这种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎.你的任务是求出有多少头牛被所有的牛认为是受欢迎的. Input 第一行两个数

【bzoj1051】 [HAOI2006]受欢迎的牛 tarjan缩点判出度算点数

[bzoj1051] [HAOI2006]受欢迎的牛 2014年1月8日7450 Description 每一头牛的愿望就是变成一头最受欢迎的牛.现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎. 这种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎.你的任务是求出有多少头牛被所有的牛认为是受欢迎的. Input 第一行两个数N,M. 接下来M行,每行两个数A,B,意思是A认为B是受欢迎的(给出的信息有可能重复,即有可能出现多个A,B) Output

[BZOJ 1051][HAOI 2006]受欢迎的牛(tarjan缩点)

http://www.lydsy.com:808/JudgeOnline/problem.php?id=1051 唔...这题好像在POJ上见过? 比较水的题,很好想出思路.牛和牛之间的关系就像有向图,牛a喜欢牛b相当于建立有向边a->b,然后在这个有向图中,每个强连通分量里的牛们相当于是相互喜欢的,把这个图缩点成DAG,DAG里如果有且仅有一个出度为0的点,则这个点对应强连通分量里的所有牛都是受欢迎的牛,如果没有出度为0的点,当然就没受欢迎的牛了,如果出度为0的点的个数大于1,则每个出度为0的

poj 2186 Popular Cows【tarjan求scc个数&amp;&amp;缩点】【求一个图中可以到达其余所有任意点的点的个数】

Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 27698   Accepted: 11148 Description Every cow's dream is to become the most popular cow in the herd. In a herd of N (1 <= N <= 10,000) cows, you are given up to M (1 <= M &

强连通分量——消息扩散(洛谷_2002)——tarjan求scc

强连通分量(scc) 缩点 建新图 找入度为0的点 大功告成 #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> #include<stack> using namespace std; inline int read(){ int t=1,num=0;char c=getchar(); while(c&g

强连通分量——间谍网络(洛谷_1262)——tarjan求scc

scc 缩点 建图 处理 #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> #include<stack> using namespace std; inline int read(){ int t=1,num=0;char c=getchar(); while(c>'9'||c<'0'){i

强连通分量——爱在心中(codevs_2822)——tarjan求scc

scc 找只有一个节点的强连通分量,标记. 第一行输出强连通分量个数(不为1个节点) 缩点 建图 找出度为0的点. 超过一个或者该点被标记,puts("-1"): else 输出答案. #include<iostream> #include<cstdio> #include<vector> #include<stack> using namespace std; inline int read(){ int t=1,num=0;char