Solution

简单的$Tarjan$题。

有大佬现成博客 就不写了 → 传送门

Code

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define rd read()
using namespace std; const int N = 1e5 + ;
const int inf = ~0U >> ; int n, m;
int head[N], tot, Head[N], Tot;
int low[N], dfn[N], cnt;
int st[N], tp, col, c[N], val[N], subsz[N], upsz[N], deg[N], bvis[N];
bool vis[N]; struct edge {
int nxt, fr, to;
}e[N], E[N]; queue<int> q; int read() {
int X = , p = ; char c = getchar();
for (; c > '' || c < ''; c = getchar())
if (c == '-') p = -;
for (; c >= '' && c <= ''; c = getchar())
X = X * + c - '';
return X * p;
} void add(int u, int v) {
e[++tot].to = v;
e[tot].fr = u;
e[tot].nxt = head[u];
head[u] = tot;
} void Add(int u, int v) {
E[++Tot].to = v;
E[Tot].fr = u;
E[Tot].nxt = Head[u];
Head[u] = Tot;
} void cmin(int &A, int B) {
if (A > B) A = B;
} void cmax(int &A, int B) {
if (A < B) A = B;
} void tarjan(int u) {
dfn[u] = low[u] = ++cnt;
vis[u] = ; st[++tp] = u;
for (int i = head[u]; i; i = e[i].nxt) {
int nt = e[i].to;
if (!dfn[nt]) {
tarjan(nt);
cmin(low[u], low[nt]);
}
else if (vis[nt]) cmin(low[u], dfn[nt]);
}
if (low[u] == dfn[u]) {
col++;
for (; tp;) {
int z = st[tp--];
c[z] = col;
vis[z] = ;
val[col]++;
if (z == u) break;
}
}
} void dfs(int u) {
vis[u] = ;
for (int i = Head[u]; i; i = E[i].nxt) {
int nt = E[i].to;
dfs(nt);
}
} int dfs2(int u) {
if (bvis[u] == ) return ;
if (bvis[u] == -) return ;
if (u == c[]) return ;
bool flag = false;
for (int i = Head[u]; i; i = E[i].nxt) {
int nt = E[i].to;
if (dfs2(nt)) {
flag = true;
cmax(upsz[u], upsz[nt] + val[u]);
}
}
bvis[u] = flag ? : -;
return flag;
} void Topsort() {
subsz[c[]] = val[c[]];
for (int i = ; i <= col; ++i)
if (!deg[i]) q.push(i);
for (int u; !q.empty(); ) {
u = q.front(); q.pop();
for (int i = Head[u]; i; i = E[i].nxt) {
int nt = E[i].to;
if (subsz[u] != -inf)
cmax(subsz[nt], subsz[u] + val[nt]);
deg[nt]--;
if (!deg[nt]) q.push(nt);
}
}
} int main()
{
n = rd; m = rd;
for (int i = ; i <= m; ++i) {
int u = rd, v = rd;
add(u, v);
}
for (int i = ; i <= n; ++i)
if (!dfn[i]) tarjan(i);
for (int i = ; i <= m; ++i) {
int u = e[i].fr, v = e[i].to;
u = c[u], v = c[v];
if (u == v) continue;
Add(u, v);
deg[v]++;
}
memset(vis, , sizeof(vis));
for (int i = ; i <= col; ++i) subsz[i] = -inf;
dfs(c[]);
Topsort();
bvis[c[]] = ;
upsz[c[]] = val[c[]];
for (int i = ; i <= col; ++i)
if (!vis[i]) dfs2(i);
int ans = val[c[]];
for (int i = ; i <= m; ++i) {
int u = e[i].fr, v = e[i].to;
u = c[u]; v = c[v];
if (u == v) continue;
if (!vis[v] || !(bvis[u] == )) continue;
cmax(ans, subsz[v] + upsz[u] - val[c[]]);
}
printf("%d\n", ans);
}

Luogu3119 草鉴定-Tarjan+Topsort的更多相关文章

  1. luogu3119/bzoj3887 草鉴定 (tarjan缩点+spfa)

    首先缩一波点,就变成了一个DAG,边权是出点的大小 那我们走到某个点的时候可能会有两种状态:已经走过反边或者没走过 于是就把一个点拆成两层(x和x+N),第二层的点表示我已经走过反边了,每层中的边和原 ...

  2. 洛谷3119 草鉴定(tarjan)

    题目大意 约翰有\(n\)块草场,编号\(1\)到\(n\),这些草场由若干条单行道相连.奶牛贝西是美味牧草的鉴赏家,她想到达尽可能多的草场去品尝牧草. 贝西总是从\(1\)号草场出发,最后回到\(1 ...

  3. luogu3119 草鉴定

    题目大意 给出一个有向图,问将图中的哪一个边翻转,会使节点1所在的强连通分量内的节点数最多.输出这个节点数. 题解 让我们看看暴力怎么做,即枚举每一条边,将其翻转,然后求节点1所在强连通分量节点数,然 ...

  4. [USACO15JAN]草鉴定Grass Cownoisseur(分层图+tarjan)

    [USACO15JAN]草鉴定Grass Cownoisseur 题目描述 In an effort to better manage the grazing patterns of his cows ...

  5. 洛谷 P3119 [USACO15JAN]草鉴定Grass Cownoisseur 解题报告

    P3119 [USACO15JAN]草鉴定Grass Cownoisseur 题目描述 约翰有\(n\)块草场,编号1到\(n\),这些草场由若干条单行道相连.奶牛贝西是美味牧草的鉴赏家,她想到达尽可 ...

  6. 【洛谷P3119】[USACO15JAN]草鉴定Grass Cownoisseur

    草鉴定Grass Cownoisseur 题目链接 约翰有n块草场,编号1到n,这些草场由若干条单行道相连.奶牛贝西是美味牧草的鉴赏家,她想到达尽可能多的草场去品尝牧草. 贝西总是从1号草场出发,最后 ...

  7. 洛谷——P3119 [USACO15JAN]草鉴定Grass Cownoisseur

    P3119 [USACO15JAN]草鉴定Grass Cownoisseur 题目描述 In an effort to better manage the grazing patterns of hi ...

  8. 洛谷P3119草鉴定

    题目 草鉴定,tarjan可以用来缩点,优化spfa的时间, 缩点之后就是一个\(DAG\)了,因此完全可以用来跑spfa上的最长路,然后枚举每条边,查看是否这条边的两个节点分别可以到达起点所在的强连 ...

  9. 洛谷 P3119 [USACO15JAN]草鉴定Grass Cownoisseur (SCC缩点,SPFA最长路,枚举反边)

    P3119 [USACO15JAN]草鉴定Grass Cownoisseur 题目描述 In an effort to better manage the grazing patterns of hi ...

随机推荐

  1. 查看docker容器的内存占用

    使用docker stats命令可以查看容器的内存,但是有时候docker stats命令获得的数据可能准确,可以参考下面这种方式 先通过docker ps -a 找到容器的container id ...

  2. 关于CoreData的用法

    有些同事觉得CoreData是一个看不懂,理解不清的神秘东东,其实ios的本地数据储存是一个sqlite数据库,一个简易的数据库,而这个CoreData是否支持所有储存的数据呢,显然不是的,站在我的角 ...

  3. List 的add()与addAll()的区别

    add 是将传入的参数作为当前List中的一个Item存储,即使你传入一个List也只会另当前的List增加1个元素addAll 是传入一个List,将此List中的所有元素加入到当前List中,也就 ...

  4. 性能测试day03_前端分析调优思路

    刚刚看到有人支持我写的博客,表示还是比较感动的,发现热心的用户在我的博客留言说“一个系统每天有200万在线用户,问我怎么设计性能场景?”,其实这个问题呢就属于业务没理清,这个问题就像我问你,一个城市一 ...

  5. MySQL学习笔记Windows篇<一> Welcome to MySQL

    MySQL安装完毕后没有图形化操作界面,图形化管理界面需要另行安装,个人比较喜欢Navicat,界面更像SQLserver: 此篇学习笔记所有操作均使用命令行中完成: 1.开启/停止服务 使用MySQ ...

  6. C++学习基础十六-- 函数学习笔记

    C++ Primer 第七章-函数学习笔记 一步一个脚印.循序渐进的学习. 一.参数传递 每次调用函数时,都会重新创建函数所有的形参,此时所传递的实参将会初始化对应的形参. 「如果形参是非引用类型,则 ...

  7. Java 原子语义同步的底层实现

    原子语义同步的底层实现 volatile volatile只能保证变量对各个线程的可见性,但不能保证原子性.关于 Java语言 volatile 的使用方法就不多说了,我的建议是 除了 配合packa ...

  8. python3 互译无线短信接口

    #!/usr/local/bin/python#-*- coding:utf-8 -*-import http.clientimport urllibimport random host = &quo ...

  9. leetcode102

    本题是广度优先遍历(BFS)实现树的层次遍历,使用队列实现. class Solution { public: vector<vector<int>> levelOrder(T ...

  10. codestyle 设置问题

    参考: https://blog.csdn.net/hugh77/article/details/43268195 使用 4 空格缩进,而非 TAB. 在小缩进(可以嵌套更深)和大缩进(更易读)之间, ...