洛谷P3119草鉴定
草鉴定,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草鉴定的更多相关文章
- 洛谷P3119 草鉴定
这个题调了一天.. 传送门 读完题目之后我们不难想出这个题是个tarjan缩点问题,因为尽量多的经过草场,所以一号点所在的强连通分量里左右的点都是不需要在进行走逆向边,所能到达的. 然后问题就落在怎么 ...
- 洛谷3119 草鉴定(tarjan)
题目大意 约翰有\(n\)块草场,编号\(1\)到\(n\),这些草场由若干条单行道相连.奶牛贝西是美味牧草的鉴赏家,她想到达尽可能多的草场去品尝牧草. 贝西总是从\(1\)号草场出发,最后回到\(1 ...
- 【题解】洛谷P3119 Grass Cownoisseur G
题面:洛谷P3119 Grass Cownoisseur G 本人最近在熟悉Tarjan的题,刷了几道蓝题后,我飘了 趾高气扬地点开这道紫题,我一瞅: 哎呦!这不是分层图吗? 突然就更飘了~~~ 用时 ...
- 洛谷 P3119 [USACO15JAN]草鉴定Grass Cownoisseur 解题报告
P3119 [USACO15JAN]草鉴定Grass Cownoisseur 题目描述 约翰有\(n\)块草场,编号1到\(n\),这些草场由若干条单行道相连.奶牛贝西是美味牧草的鉴赏家,她想到达尽可 ...
- 洛谷——P3119 [USACO15JAN]草鉴定Grass Cownoisseur
P3119 [USACO15JAN]草鉴定Grass Cownoisseur 题目描述 In an effort to better manage the grazing patterns of hi ...
- 洛谷 P3119 [USACO15JAN]草鉴定Grass Cownoisseur (SCC缩点,SPFA最长路,枚举反边)
P3119 [USACO15JAN]草鉴定Grass Cownoisseur 题目描述 In an effort to better manage the grazing patterns of hi ...
- 【洛谷P3119】[USACO15JAN]草鉴定Grass Cownoisseur
草鉴定Grass Cownoisseur 题目链接 约翰有n块草场,编号1到n,这些草场由若干条单行道相连.奶牛贝西是美味牧草的鉴赏家,她想到达尽可能多的草场去品尝牧草. 贝西总是从1号草场出发,最后 ...
- 洛谷P3119 USACO15JAN 草鉴定
题目描述 In an effort to better manage the grazing patterns of his cows, Farmer John has installed one-w ...
- 洛谷 P3119 [USACO15JAN]草鉴定Grass Cownoisseur
屠龙宝刀点击就送 Tarjan缩点+拓扑排序 以后缩点后建图看n范围用vector ,或者直接用map+vector 结构体里数据要清空 代码: #include <cstring> #i ...
随机推荐
- Account locked due to 25 failed logins
Account locked due to 25 failed logins pam_tally2 --user=ops #查看 pam_tally2 --user=ops --reset # ...
- git 如何取消add操作
可以直接使用命令 git reset HEAD 这个是整体回到上次一次操作 绿字变红字(撤销add) 如果是某个文件回滚到上一次操作: git reset HEAD 文件名 红字变无 (撤销 ...
- RabbitMq 报错记录
只记录本人当时遇到的情况,仅作参考 添加消息队列报错:The connection cannot support any more channels. Consider creating a new ...
- 遗传算法python实现
最近看了一下遗传算法,使用轮盘赌选择染色体,使用单点交叉,下面是代码实现(python3) import numpy as np import random from scipy.optimize i ...
- wstngfw中配置freeradius
wstngfw中配置freeradius Radius为各种网络设备和服务提供了一个认证来源. Radius认证常用于***.入网门户.交换机.路由器和防火墙.Radius认证比在网络上的不同设备跟踪 ...
- java中对List中的元素进行排序
Collections对List集合中的数据进行排序 有时候需要对集合中的元素按照一定的规则进行排序,这就需要用到 Java中提供的对集合进行操作的工具类Collections,其中的sort方法 N ...
- 【转载】C#中将字符串分割成字符数组
在C#中字符串类型String是由一系列的单个字符组合而成,其实可以通过字符串String对象ToCharArray()方法来将字符串中的元素逐一存在数据类型为Char的一维数组中. 例如将字符str ...
- linux 的GUNB修复问题
1.意外断电,kali linux 虚拟机没有正常关机的时候 , 突然断电之后重启电脑之后,kali linux 直接黑屏了无法进入系统.如下面的界面 光标一直在闪烁. 这里可以使用 快捷键 同时按住 ...
- java--反射的基本概念
反射的基本概念 如果正常的情况下,如果使用一个类,则必须按照如下的步骤操作: 使用import 导入类所在的包:(类:java.lang.Class) 明确的使用类名称或借口名称定义对象: 通过关键字 ...
- Go语言中的IO操作、Flag包以及urfave/cli命令行框架
一.格式化输入和输出 1.从终端获取用户的输入 fmt.Scanf 空格作为分隔符,占位符和格式化输出的一致 fmt.Scan 从终端获取用户的输入,存储在Scanln中的参数里,空格和换行符作为 ...