P3119 [USACO15JAN]草鉴定
约翰有n块草场,编号1到n,这些草场由若干条单行道相连。奶牛贝西是美味牧草的鉴赏家,她想到达尽可能多的草场去品尝牧草。
贝西总是从1号草场出发,最后回到1号草场。她想经过尽可能多的草场,贝西在通一个草场只吃一次草,所以一个草场可以经过多次。
因为草场是单行道连接,这给贝西的品鉴工作带来了很大的不便,贝西想偷偷逆向行走一次,但最多只能有一次逆行。问,贝西最多能吃到多少个草场的牧草。
输入:
第一行:草场数n,道路数m。
以下m行,每行x和y表明有x到y的单向边,不会有重复的道路出现。
输出:
一个数,逆行一次最多可以走几个草场。
输入 #1
7 10
1 2
3 1
2 5
2 4
3 7
3 5
3 6
6 5
7 2
4 7 输出 #1
6
好久没有这么正式的将题面搬过来了;
显然需要tarjan求强连通分量;
但是我只会到这里,但是看题;
允许一条边反向,有点眼熟,啊,那个,就是那个
我们先缩点,dijkstra正向求最长路,再反向求最长路
枚举反向的边;
dis1[x]+dis2[v]-sum[belong[1]];
但是我们要保证能回去
#include<cstdio>
#include<cstring>
#include<queue>
#include<stack>
#include<algorithm>
using namespace std;
const int maxn=1e5+;
int n,m,pre[maxn],last[maxn],other[maxn],l;
int pre0[maxn],last0[maxn],other0[maxn],l0;
void add0(int x,int y)
{
l0++;
pre0[l0]=last0[x];
last0[x]=l0;
other0[l0]=y;
}
int dfn[maxn],low[maxn],cnt;
void add(int x,int y)
{
l++;
pre[l]=last[x];
last[x]=l;
other[l]=y;
}
int pre2[maxn],last2[maxn],other2[maxn],l2;
void add2(int x,int y)
{
l2++;
pre2[l2]=last2[x];
last2[x]=l2;
other2[l2]=y;
} stack<int> s;
int belong[maxn],qw; void dfs(int x)
{
dfn[x]=low[x]=++cnt;
s.push(x);
for(int p=last[x];p;p=pre[p])
{
int v=other[p];
if(!dfn[v])
{
dfs(v);
low[x]=min(low[x],low[v]);
}
else if(!belong[v])
{
low[x]=min(low[x],dfn[v]);
}
}
if(dfn[x]==low[x])
{
belong[x]=++qw;
//printf("%d ",qw);
while()
{
int y=s.top();
s.pop();
belong[y]=qw;
if(x==y) break;
}
}
} int sum[maxn];
int ans;
int vis[maxn];
int dis1[maxn],dis2[maxn];
priority_queue<pair<int,int> >q;
void dijkstra(int x)
{
memset(vis,,sizeof(vis));
dis1[x]=sum[x];
q.push(make_pair(dis1[x],x));
while(!q.empty())
{
int u=q.top().second;
q.pop();
// printf("%d\n!",u);
// printf("%d\n?",last[u]);
// if(vis[u]) continue;
// vis[u]=1;
for(int p=last0[u];p;p=pre0[p])
{
int v=other0[p];
//printf("!!");
if(dis1[v]<dis1[u]+sum[v])
{
dis1[v]=dis1[u]+sum[v];
q.push(make_pair(dis1[v],v));
//printf("%d\n",dis1[v]);
}
}
}
} void dijkstra2(int x)
{
memset(vis,,sizeof(vis));
dis2[x]=sum[x];
q.push(make_pair(dis2[x],x));
while(!q.empty())
{
int u=q.top().second;
q.pop();
// if(vis[u]) continue;
// vis[u]=1;
for(int p=last2[u];p;p=pre2[p])
{
int v=other2[p];
if(dis2[v]<dis2[u]+sum[v])
{
dis2[v]=dis2[u]+sum[v];
q.push(make_pair(dis2[v],v));
}
}
}
} int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
}
for(int i=;i<=n;i++)
{
if(!dfn[i]) dfs(i);
} //memset(pre,0,sizeof(pre)); for(int i=;i<=n;i++)
{
sum[belong[i]]++;
}
//for(int i=1;i<=qw;i++) printf("%d ",sum[i]);
for(int i=;i<=n;i++)
{
for(int p=last[i];p;p=pre[p])
{
int v=other[p];
if(belong[i]!=belong[v])
{
add0(belong[i],belong[v]);
add2(belong[v],belong[i]);
}
}
}
ans=sum[belong[]];
dijkstra(belong[]);
dijkstra2(belong[]);
//for(int i =1;i<=n;i++) printf("%d ",dis1[i]);
memset(vis,,sizeof(vis));
for(int i=;i<=n;i++)
{
if(vis[belong[i]]||!dis1[belong[i]]) continue;
vis[belong[i]]=;
int x=belong[i];
for(int p=last2[x];p;p=pre2[p])
{
int v=other2[p];
if(!dis2[v]) continue;
ans=max(ans,dis1[x]+dis2[v]-sum[belong[]]);
}
}
printf("%d",ans);
return ;
}
P3119 [USACO15JAN]草鉴定的更多相关文章
- 洛谷 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
题目描述 In an effort to better manage the grazing patterns of his cows, Farmer John has installed one-w ...
- 洛谷P3119 USACO15JAN 草鉴定
题目描述 In an effort to better manage the grazing patterns of his cows, Farmer John has installed one-w ...
- 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 分层图或者跑两次最长路
https://www.luogu.org/problemnew/show/P3119 题意 有一个有向图,允许最多走一次逆向的路,问从1再走回1,最多能经过几个点. 思路 (一)首先先缩点.自己在缩 ...
- P3119 [USACO15JAN]草鉴定[SCC缩点+SPFA]
题目描述 约翰有n块草场,编号1到n,这些草场由若干条单行道相连.奶牛贝西是美味牧草的鉴赏家,她想到达尽可能多的草场去品尝牧草. 贝西总是从1号草场出发,最后回到1号草场.她想经过尽可能多的草场,贝西 ...
- [Luogu P3119] [USACO15JAN]草鉴定Grass Cownoisseur (缩点+图上DP)
题面 传送门:https://www.luogu.org/problemnew/show/P3119 Solution 这题显然要先把缩点做了. 然后我们就可以考虑如何处理走反向边的问题. 像我这样的 ...
随机推荐
- NodeJS入门--环境搭建 IntelliJ IDEA
NodeJS入门–环境搭建 IntelliJ IDEA 本人也刚开始学习NodeJS,所以以此做个笔记,欢迎大家提出意见. 1.首先 下载安装NodeJS,下载安装IntelliJ IDEA 2.接下 ...
- centos7上使用git clone出现问题
centos 7 git clone时出现不支持协议版本的问题 unable to access 'https://github.com/baloonwj/TeamTalk.git/': Peer ...
- 【转载】C#通过StartWith和EndWith方法判断字符串是否以特定字符开始或者结束
C#开发过程中针对字符串String类型的操作是常见操作,有时候业务需要判断某个字符串是否以特定字符开头或者特定字符结束,此时就可使用StartsWith方法来判断目标字符串是否以特定字符串开头,通过 ...
- 布隆过滤算法体会(BlooomFilter)
在一个m位的位数组里,一个字符串经过k次hash随机分布到k个位置. http://www.cnblogs.com/aspnethot/articles/3442813.html 布隆filter数据 ...
- Android笔记(三十四) Android中线程之间的通信(六)Handle中的post()方法详解
我们之前都是使用sendMessage()方法来发送消息,使用handleMessage来处理消息的,今天我们来看另外一种方法,先看代码: package cn.lixyz.handlertest; ...
- 记录java+testng运行selenium(四)--- 结构说明
一图:主要是driver文件所在目录,及ini配置文件所在位置. 这两个文件一般我是放在其它目录下,不跟随项目所在目录 二图:用例操作类及用例执行类所在位置. 下图中有接口代码及功能代码组成,之前的文 ...
- java - day012 - 异常 , throws, throw , IO ,RandomAccessFile
异常 封装错误信息的对象 错误信息 类型 例如: NullPointerExce 空指针 提示消息 出错的行号 异常的继承结构 Throwable | - Error 系统级错误 | ...
- html的基础知识点
小编为大家带来html的基础知识Web 标准的好处让Web的发展前景更广阔 内容能被更广泛的设备访问更容易被搜寻引擎搜索降低网站流量费用使网站更易于维护提高页面浏览速度Web 标准构成Web标准不是某 ...
- AD19新功能之Gloss Selected(修线)
一.强大的修线功能 鼠标从右下往左上框选线,然后按 tab 键,选中需要修的走线 然后执行 “Route”栏下 “Gloss Selected”命令进行修线: 二.循环至推模式 AD19默认为推挤模式 ...
- C#一些不太熟悉的类——扩展学习
Process.CloseMainWindow Method 通过向进程的主窗口发送关闭消息来关闭拥有用户界面的进程. 注解 进程执行时,其消息循环处于等待状态. 每次操作系统将 Windows 消息 ...