题目

草鉴定,tarjan可以用来缩点,优化spfa的时间,

缩点之后就是一个\(DAG\)了,因此完全可以用来跑spfa上的最长路,然后枚举每条边,查看是否这条边的两个节点分别可以到达起点所在的强连通分量。(因为要返回到1点)。然后更新答案就可以了。

可是为什么要缩点呢,因为只能逆行一次,逆行之后通过在强连通分量上的点可以把强连通分量上的所有点全都遍历一次,最后还可以回到强连通分量上的起点,所以可以tarjan缩点。

#include <bits/stdc++.h>
using namespace std;
int n, m, lin[100010], lne[100100], lf[101000], dfn[100010], low[100100], vis[100100], belong[100100], dis[1001000], dis2[101000], color, tot, cnt, ans, cntne, cntf;
stack <int> s;
int sum[100100];struct edg {
int to, nex;
}e[1000100], f[1000100], ne[100100];
inline void add(int u, int v)
{
e[++cnt].to = v;
e[cnt].nex = lin[u];
lin[u] = cnt;
}
inline void add2(int u, int v)
{
ne[++cntne].to = v;
ne[cntne].nex = lne[u];
lne[u] = cntne;
}
inline void addf(int u, int v)
{
f[++cntf].to = v;
f[cntf].nex = lf[u];
lf[u] = cntf;
}
inline void tarjan(int u)
{
dfn[u] = low[u] = ++tot;
s.push(u); vis[u] = 1;
for(int i = lin[u]; i; i = e[i].nex)
{
int v = e[i].to;
if(!dfn[v]) {
tarjan(v);
low[u] = min(low[u],low[v]);
}
else if(vis[v]) low[u] = min(low[u],dfn[v]);
}
if(low[u] == dfn[u])
{
int v = -3;
color++;
do
{
v = s.top(); s.pop();
belong[v] = color;
vis[v] = 0;
sum[color]++;
} while (u != v);
}
}
int inq[101000];
inline void spfa()
{
memset(dis, -123, sizeof(dis));
queue <int> q;
dis[belong[1]] = sum[belong[1]];
q.push(belong[1]);
while (!q.empty())
{
int cur = q.front(); q.pop(); inq[cur] = 0;
for (int i = lne[cur]; i; i = ne[i].nex)
{
int to = ne[i].to;
if (dis[cur] + sum[to] > dis[to])
{
dis[to] = dis[cur] + sum[to];
if (!inq[to])
inq[to] = 1, q.push(to);
}
}
}
}
inline void sf()
{
memset(dis2, -123, sizeof(dis2));
queue <int> q;
// memset(vis, 0, sizeof(vis));
dis2[belong[1]] = sum[belong[1]]; q.push(belong[1]);
while (!q.empty())
{
int cur = q.front(); q.pop(); inq[cur] = 0;
for (int i = lf[cur]; i; i = f[i].nex)
{
int to = f[i].to;
if(dis2[cur] + sum[to] > dis2[to])
{
dis2[to] = dis2[cur] + sum[to];
if (!inq[to])
inq[to] = 1, q.push(to);
}
}
}
}
int b1[100100], b2[101000];
void dfs1(int u)
{
b1[u] = 1;
for (int i = lne[u]; i; i = ne[i].nex)
if (!b1[ne[i].to])
dfs1(ne[i].to);
}
void dfs2(int u)
{
b2[u] = 1;
for (int i = lf[u]; i; i = f[i].nex)
if (!b2[f[i].to])
dfs2(f[i].to);
}
inline void init()
{
scanf("%d%d", &n, &m);
for (int i = 1, u, v; i <= m; i++)
scanf("%d%d", &u, &v), add(u, v);
for (int i = 1; i <= n; i++)
if (!dfn[i]) tarjan(i); }
inline void jiantu()
{
for (int i = 1; i <= n; i++)
for (int j = lin[i]; j; j = e[j].nex)
{
int to = e[j].to;
if (belong[i] != belong[to]) add2(belong[i], belong[to]), addf(belong[to], belong[i]);
}
}
int main()
{
init();
jiantu();
dfs1(belong[1]);
dfs2(belong[1]);
spfa();
sf();
for (int i = 1; i <= color; i++)
if (b1[i])
for (int j = lf[i]; j; j = f[j].nex)
if (b2[f[j].to])
ans = max(ans, dis2[f[j].to] + dis[i]);
ans -= sum[belong[1]];
printf("%d\n", ans);
return 0;
}

洛谷P3119草鉴定的更多相关文章

  1. 洛谷P3119 草鉴定

    这个题调了一天.. 传送门 读完题目之后我们不难想出这个题是个tarjan缩点问题,因为尽量多的经过草场,所以一号点所在的强连通分量里左右的点都是不需要在进行走逆向边,所能到达的. 然后问题就落在怎么 ...

  2. 洛谷3119 草鉴定(tarjan)

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

  3. 【题解】洛谷P3119 Grass Cownoisseur G

    题面:洛谷P3119 Grass Cownoisseur G 本人最近在熟悉Tarjan的题,刷了几道蓝题后,我飘了 趾高气扬地点开这道紫题,我一瞅: 哎呦!这不是分层图吗? 突然就更飘了~~~ 用时 ...

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

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

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

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

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

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

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

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

  8. 洛谷P3119 USACO15JAN 草鉴定

    题目描述 In an effort to better manage the grazing patterns of his cows, Farmer John has installed one-w ...

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

    屠龙宝刀点击就送 Tarjan缩点+拓扑排序 以后缩点后建图看n范围用vector ,或者直接用map+vector 结构体里数据要清空 代码: #include <cstring> #i ...

随机推荐

  1. Git和Github的介绍、简单操作、冲突(上)

    目的:   1.git与github简介  2.Git与SVN区别 3.Github 的简单使用 4.下载安装Git-20-64-bit.exe   5.Git常用命令 5.1Git命令使用场景 5. ...

  2. Thread interrupted() 线程的中断

    问题: 1.线程的中断方式. 2.为什么中断阻塞中的线程,会抛出异常. 代码示例: package com.hdwl.netty; public class ThreadInterrupted { p ...

  3. Fatal error:Call to undefined function mysqli_connect() in .php line 报错

    这样的问题,多半是PHP配置问题. 修改php配置文件 1.在php(版本:php-7.2.7-Win32-VC15-x64)文件夹中一开始不会看到php.ini,而是php.ini-developm ...

  4. Android NDK 学习之调用Java函数

    本博客主要是在Ubuntu 下开发,且默认你已经安装了Eclipse,Android SDK, Android NDK, CDT插件. 在Eclipse中添加配置NDK,路径如下Eclipse-> ...

  5. iOS 内存管理的一点小问题

    现在大家的项目应该基本都是ARC了,如果还是MRC的话,赶紧转换到ARC吧!最近被临时拉过去开发iPad,由于项目原因,还是使用的MRC.今天在调部分界面的时候,发现一段代码,我怎么看都怎么觉得怪怪的 ...

  6. Jerry Wang从2017年到2019年的自由泳学习笔记

    打腿 把注意力调整到脚部,尽量不要让他打出水面,因为在空气中大腿完全是无用功,但是如果只是脚跟出水一点,倒也没什么关心,但是主观上,要控制一下,如果你听到你的打腿是"咚咚咚咚"这样 ...

  7. nn.Conv2d 参数及输入输出详解

    Torch.nn.Conv2d(in_channels,out_channels,kernel_size,stride=1,padding=0,dilation=1,groups=1,bias=Tru ...

  8. Nginx基本参数调优

    Nginx基本参数 #运行用户 user nobody; #worker进程的个数:通常应该为物理CPU核数减1: #可以为”auto”,实现自动设定(worker_processes  auto) ...

  9. Java stackoverflowerror异常与outofmemoryerror异常区别

    1.stackoverflow: 每当java程序启动一个新的线程时,java虚拟机会为他分配一个栈,java栈以帧为单位保持线程运行状态:当线程调用一个方法是,jvm压入一个新的栈帧到这个线程的栈中 ...

  10. 0015SpringBoot结合thymeleaf实现点击菜单高亮显示

    1.点击菜单,经过Controller层处理,正常定位到视图页面 2.编写抽象出公共片段的html,根据参数判断是否加高亮样式 3.多个目标页面引用步骤2中抽象出的公共片段,传不同的参数 具体实现如下 ...