[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,最多能经过几个点. 思路 (一)首先先缩点.自己在缩 ...
随机推荐
- Python练习题 042:Project Euler 014:最长的考拉兹序列
本题来自 Project Euler 第14题:https://projecteuler.net/problem=14 ''' Project Euler: Problem 14: Longest C ...
- 解决Dubbo无法发布被事务代理的Service问题
在HelloServiceImpl类上加入@Transactional注解后,虽然工程可以正常跑起来,但是通过dubbo管理控制台可以看到里面并没有服务发布上来. 此时启动服务提供者和服务消费者,并访 ...
- 060 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 07 冒泡排序
060 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 07 冒泡排序 本文知识点:冒泡排序 冒泡排序 实际案例分析冒泡排序流程 第1轮比较: 第1轮比较的结果:把最 ...
- C++中union的使用方法
转载:https://blog.csdn.net/hou09tian/article/details/80816445 1 概述 1.1 定义 union即为联合,它是一种特殊的类.通过关键字unio ...
- Black-Lives-Matter-Resources
下载 Black-Lives-Matter-ResourcesBlack-Lives-Matter-Resources 关于最近在美国发生的事件的资源列表 链接 描述 由于(可选) 插入链接 在这里插 ...
- OAuth 2.0 Server PHP实现示例
需求实现三方OAuth2.0授权登录 使用OAuth服务OAuth 2.0 Server PHP 环境nginx mysqlphp 框架Yii 一 安装 项目目录下安装应用 composer.phar ...
- Oracle报错>记录被另外一个用户锁定
原因 当一个用户对数据进行修改时,若没有进行提交或者回滚,Oracle不允许其他用户修改该条数据,在这种情况下修改,就会出现:"记录被另外一个用户锁定"错误. 解决 查询用户.数据 ...
- volatile、ThreadLocal的使用场景和原理
并发编程中的三个概念 原子性 一个或多个操作.要么全部执行完成并且执行过程不会被打断,要么不执行.最常见的例子:i++/i--操作.不是原子性操作,如果不做好同步性就容易造成线程安全问题. 可见性 多 ...
- 多测师讲解selenium--常用关键字归纳-_高级讲师肖sir
常见的定位方式: 1.通过id定位 id=kw 2.通过name定位 name=wd 3.通过xpath相对路径定位:xpath=//*[@id="kw"] 4.通过两个属性值定位 ...
- react中 受控组件和 非受控组件 浅析
一 受控组件 顾名思义,受控 也就是能够被控制,简而言之也就是 该组件ui的显示或者内部state逻辑的变化依赖外部的 props的传入. 二 非受控组件 顾名思义,非受控,也就是内部的视图变化,st ...