[Luogu P3119] [USACO15JAN]草鉴定Grass Cownoisseur (缩点+图上DP)
题面
传送门:https://www.luogu.org/problemnew/show/P3119




Solution
这题显然要先把缩点做了。
然后我们就可以考虑如何处理走反向边的问题。
像我这样的蒟蒻,当然是使用搜索,带记忆化的那种(滑稽)。
考虑设f(i,j)表示到达第i个点,还能走j次反向边,所能到达的最多的点的数量。
转移可以表示为:

如果x能到达1所在的强连通分量或max出来的值不为0,说明当前状态可行,否则不可行。
然后用记忆化搜索表达出来就OK了
Code
#include<iostream>
#include<cstdio>
#include<vector>
#include<stack>
#include<cstring>
using namespace std;
long long read()
{
long long x=0,f=1; char c=getchar();
while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}
while(isdigit(c)){x=x*10+c-'0';c=getchar();}
return x*f;
}
const int N=100000+100;
struct road
{
int to,IsBack;
road (int A,int B)
{
to=A,IsBack=B;
}
};
vector <int> e[N];
vector <road> e2[N];
int belong[N],nd_tot,nd_to,low[N],dfn[N],InStack[N],cnt[N];
stack <int> st;
void Tarjan(int now)
{
low[now]=dfn[now]=++nd_to;
InStack[now]=true;
st.push(now);
for(int i=0;i<int(e[now].size());i++)
if(dfn[e[now][i]]==0)
{
Tarjan(e[now][i]);
low[now]=min(low[now],low[e[now][i]]);
}
else if(InStack[e[now][i]]==true)
low[now]=min(low[now],low[e[now][i]]);
if(low[now]==dfn[now])
{
nd_tot++;
while(st.empty()==false)
{
int temp=st.top();
st.pop();
belong[temp]=nd_tot;
InStack[temp]=false;
cnt[nd_tot]++;
if(temp==now)
break;
}
}
}
int n,m,S,f[N][2];
int dfs(int now,int back)
{
if(f[now][back]>=0) return f[now][back];
int t_ans=0;
bool OK=false;
for(int i=0;i<int(e2[now].size());i++)
if(e2[now][i].to!=S and back-e2[now][i].IsBack>=0)
t_ans=max(t_ans,dfs(e2[now][i].to,back-e2[now][i].IsBack));
else if(back>=e2[now][i].IsBack)
OK=true;
if(t_ans!=0 or OK==true)
return f[now][back]=t_ans+cnt[now];
else
return f[now][back]=0;
}
int main()
{
n=read(),m=read();
for(int i=1;i<=n;i++)
e[i].reserve(4),
e2[i].reserve(4);
for(int i=1;i<=m;i++)
{
int s=read(),t=read();
e[s].push_back(t);
} for(int i=1;i<=n;i++)
if(dfn[i]==0)
Tarjan(i);
S=belong[1];
for(int i=1;i<=n;i++)
for(int j=0;j<int(e[i].size());j++)
if(belong[i]!=belong[e[i][j]])
{
e2[belong[i]].push_back(road(belong[e[i][j]],0));
e2[belong[e[i][j]]].push_back(road(belong[i],1));
} memset(f,0x80,sizeof f);
int ans=0;
for(int i=0;i<int(e2[S].size());i++)
ans=max(ans,dfs(e2[S][i].to,1-e2[S][i].IsBack)); printf("%d",ans+cnt[S]);
return 0;
}
C++(正解)
[Luogu P3119] [USACO15JAN]草鉴定Grass Cownoisseur (缩点+图上DP)的更多相关文章
- luogu P3119 [USACO15JAN]草鉴定Grass Cownoisseur
题目描述 In an effort to better manage the grazing patterns of his cows, Farmer John has installed one-w ...
- 洛谷 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 解题报告
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 ...
- [USACO15JAN]草鉴定Grass Cownoisseur(分层图+tarjan)
[USACO15JAN]草鉴定Grass Cownoisseur 题目描述 In an effort to better manage the grazing patterns of his cows ...
- Luogu 3119 [USACO15JAN]草鉴定Grass Cownoisseur
思路很乱,写个博客理一理. 缩点 + dp. 首先发现把一个环上的边反向是意义不大的,这样子不但不好算,而且相当于浪费了一次反向的机会.反正一个强连通分量里的点绕一遍都可以走到,所以我们缩点之后把一个 ...
- P3119 [USACO15JAN]草鉴定Grass Cownoisseur
题目描述 In an effort to better manage the grazing patterns of his cows, Farmer John has installed one-w ...
- 洛谷—— P3119 [USACO15JAN]草鉴定Grass Cownoisseur || BZOJ——T 3887: [Usaco2015 Jan]Grass Cownoisseur
http://www.lydsy.com/JudgeOnline/problem.php?id=3887|| https://www.luogu.org/problem/show?pid=3119 D ...
- P3119 [USACO15JAN]草鉴定Grass Cownoisseur 分层图或者跑两次最长路
https://www.luogu.org/problemnew/show/P3119 题意 有一个有向图,允许最多走一次逆向的路,问从1再走回1,最多能经过几个点. 思路 (一)首先先缩点.自己在缩 ...
随机推荐
- safari 浏览器版本升级后提示“此网页出现问题,已重新载入网页” 解决办法
safari回退条件 版本回退的前提是关闭电脑的SIP机制,命令行 csrutil status 检测状态.Mac os 10.14以下版本回退Safari后插件还是可以用的,升了新系统退了也没法用了 ...
- AD15使用笔记
AD15使用笔记 1.板内孔开洞 步骤:选中图形->Tools->Convert->Creat Borad Cutout From Selected Primitives;
- 搭建go-stress-testing压力测试
参考地址:https://github.com/link1st/go-stress-testing安装golang环境 yum install -y golang 下载软件包 wget -q http ...
- fio硬盘测速windows+linux
一.FIO工具简介 Fio工具的介绍网上有很多,都是可以通用的,这里就不做太多个人描述了,直接借鉴一下 fio是一种I / O工具,用于基准测试和压力/硬件验证.它支持19种不同类型的I / O引擎( ...
- .NET Core使用FluentEmail发送邮件
前言 在实际的项目开发中,我们会遇到许多需要通过程序发送邮件的场景,比如异常报警.消息.进度通知等等.一般情况下我们使用原生的SmtpClient类库居多,它能满足我们绝大多数场景.但是使用起来不够简 ...
- ubuntu 19.10 中防火墙iptables配置
$sudo which iptables /usr/sbin/iptables说明有安装 如果没有安装,那么使用sudo apt-get install iptables 安装. 刚装机,是这个样 ...
- 面经手册 · 第13篇《除了JDK、CGLIB,还有3种类代理方式?面试又卡住!》
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 编程学习,先铺宽度还是挖深度? 其实技术宽度与技术深度是相辅相成的,你能了解多少技术 ...
- pytest文档43-元数据使用(pytest-metadata)
前言 什么是元数据?元数据是关于数据的描述,存储着关于数据的信息,为人们更方便地检索信息提供了帮助. pytest 框架里面的元数据可以使用 pytest-metadata 插件实现.文档地址http ...
- lumen-ioc容器测试 (6)
lumen-ioc容器测试 (1) lumen-ioc容器测试 (2) lumen-ioc容器测试 (3) lumen-ioc容器测试 (4) lumen-ioc容器测试 (5) lumen-ioc容 ...
- faker切换user-agent
import random import requests url = "http://tool.yeves.cn" import faker fake = faker.Faker ...