Luogu P2863 [USACO06JAN]The Cow Prom S
作者:互联网
思路
这个题就是纯正的Tarjan模板题,关于难以理解的、玄学的low数组,建议感性理解。网上的解释千姿百态,啥样的都有,有的对有的错,看多了反而会晕。所以建议Tarjan模板基本的几个部分多打几遍,
熟练了就好(不建议强求理解)。
Code
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define MAXN 20010
#define MAXM 50010
int n, m, idx;
int head[MAXM], cnt;
int dfn[MAXN], low[MAXN];
int stk[MAXN], top, size[MAXN];
int flag[MAXN], bel[MAXN], scc;
struct node{
int nxt, to;
} edge[MAXM];
inline int read(void){
int f = 1, x = 0;char ch;
do{ch = getchar();if(ch=='-')f = -1;} while (ch < '0' || ch > '9');
do{ x = x * 10 + ch - '0';ch = getchar();} while (ch >= '0' && ch <= '9');
return f * x;
}
inline int _min(int x,int y){
return x < y ? x : y;
}
inline void add_edge(int x,int y){
++cnt;
edge[cnt].nxt = head[x];
edge[cnt].to = y;
head[x] = cnt;
return;
}
void tarjan(int k){
dfn[k] = low[k] = ++idx;
stk[++top] = k;
flag[k] = 1;
for (int i = head[k]; i; i = edge[i].nxt){
int v = edge[i].to;
if(!dfn[v])
tarjan(v), low[k] = _min(low[k], low[v]);
else if(flag[v]) low[k] = _min(low[k], dfn[v]);//这几个min代码量也不大,建议背诵(大部分Tarjan题都不会对这两个min做出变动)
}
if(dfn[k]==low[k]){
int now = -1;
++scc;
while(now!=k){
now = stk[top], --top;
flag[now] = 0;
++size[scc];
bel[now] = scc;
}//每次找到返祖边(环)后统计答案
}
}
int main(){
n = read(), m = read();
for (int i = 1; i <= m; ++i){
int u = read(), v = read();
add_edge(u, v);//连有向边
}
for (int i = 1; i <= n; ++i)
if(!dfn[i]) tarjan(i);//注意原图可能不连通
// for (int i = 1; i <= n; ++i){
// printf("dfn[%d]=%d,low[%d]=%d\n", i, dfn[i], i, low[i]);
// }
int ans = 0;
for (int i = 1; i <= scc; ++i)
if(size[i]>1) ++ans;//统计大小大于1的强连通分量个数
printf("%d\n", ans);
return 0;
}
标签:ch,int,Luogu,ans,P2863,Prom,MAXN,MAXM,include 来源: https://www.cnblogs.com/ShadowFlowhyc/p/13380898.html