用户工具

站点工具


2020-2021:teams:hotpot:tarjan

差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
2020-2021:teams:hotpot:tarjan [2020/05/13 17:33]
misakatao 更新
2020-2021:teams:hotpot:tarjan [2020/05/13 20:25] (当前版本)
misakatao 更新
行 35: 行 35:
 回溯到1,有dfn[1]==low[1],从栈中弹出3、4、2、1,它们构成一个强连通分量。 回溯到1,有dfn[1]==low[1],从栈中弹出3、4、2、1,它们构成一个强连通分量。
  
 +======例题======
  
 +=====BZOJ1051——受欢迎的牛=====
 +
 +====题目大意====
 +
 +有$N$头牛,$M$对关系$(a,​b)$表示$a$认为$b$受欢迎,如果$a$认为$b$受欢迎,$b$认为$c$受欢迎,那么$a$也认为$c$受欢迎,问有多少头牛受所有其他的牛欢迎。
 +
 +====解题思路====
 +
 +首先利用Tarjan找到强连通分量然后缩点,接下来我们会发现如果只有一个点出度为0那么就满足答案,否则结果为0。所以我们找到这个出度为0的点代表的强连通分量的大小即可。
 +
 +====代码实现====
 +
 +<code cpp>
 +#include <map>
 +#include <set>
 +#include <​ctime>​
 +#include <​cmath>​
 +#include <​stack>​
 +#include <​queue>​
 +#include <​vector>​
 +#include <​cstdio>​
 +#include <​cstdlib>​
 +#include <​cstring> ​
 +#include <​iostream>​
 +#include <​algorithm>​
 +using namespace std;
 +
 +const int maxn = 10005;
 +const int maxm = 50005;
 +
 +int n, m, tot, top, scc = 0, color[maxn],​ dfn[maxn], low[maxn], stk[maxn], d[maxn], siz[maxn], ins[maxn];
 +int u[maxm], v[maxm], ans = 0;
 +vector<​int>​ g[maxn];
 +
 +inline void tarjan(int x)
 +{
 + dfn[x] = low[x] = ++tot;
 + stk[++top] = x;
 + ins[x] = 1;
 + int s = g[x].size();​
 + for(int i = 0;i < s;++i)
 + {
 + if(!dfn[g[x][i]])
 + {
 + tarjan(g[x][i]);​
 + low[x] = min(low[x], low[g[x][i]]);​
 + }
 + else
 + low[x] = min(low[x], dfn[g[x][i]]);//​这里不是low[g[x][i]]是因为g[x][i]的low值可能还没更新过
 + }
 +
 + if(dfn[x] == low[x])
 + {
 + int now = -1;
 + ++scc;
 + while(now != x)
 + {
 + now = stk[top];
 + top--;
 + ins[now] = 0;
 + color[now] = scc;
 + ++siz[scc];​
 + }
 + }
 +}
 +
 +int main()
 +{
 + scanf("​%d%d",​ &n, &m);
 + for(int i = 1;i <= m;++i)
 + {
 + scanf("​%d%d",​ &u[i], &v[i]);
 + g[u[i]].push_back(v[i]);​
 + }
 +
 + for(int i = 1;i <= n;++i)
 + if(!dfn[i])
 + tarjan(i);​
 +
 + for(int i = 1;i <= m;++i)
 + if(color[u[i]] != color[v[i]])
 + ++d[color[u[i]]];​
 +
 + for(int i = 1;i <= scc;++i)
 + {
 + if(!d[i])
 + {
 + if(ans > 0)
 + {
 + ans = 0;
 + break;
 + }
 + ans = siz[i];
 + }
 + }
 +
 + printf("​%d\n",​ ans);
 +
 + return 0;
 +}
 +</​code>​
  
  
2020-2021/teams/hotpot/tarjan.1589362411.txt.gz · 最后更改: 2020/05/13 17:33 由 misakatao