题目描述

In an effort to better manage the grazing patterns of his cows, Farmer John has installed one-way cow paths all over his farm. The farm consists of N fields, conveniently numbered 1..N, with each one-way cow path connecting a pair of fields. For example, if a path connects from field X to field Y, then cows are allowed to travel from X to Y but not from Y to X. Bessie the cow, as we all know, enjoys eating grass from as many fields as possible. She always starts in field 1 at the beginning of the day and visits a sequence of fields, returning to field 1 at the end of the day. She tries to maximize the number of distinct fields along her route, since she gets to eat the grass in each one (if she visits a field multiple times, she only eats the grass there once). As one might imagine, Bessie is not particularly happy about the one-way restriction on FJ's paths, since this will likely reduce the number of distinct fields she can possibly visit along her daily route. She wonders how much grass she will be able to eat if she breaks the rules and follows up to one path in the wrong direction. Please compute the maximum number of distinct fields she can visit along a route starting and ending at field 1, where she can follow up to one path along the route in the wrong direction. Bessie can only travel backwards at most once in her journey. In particular, she cannot even take the same path backwards twice. 给一个有向图,然后选一条路径起点终点都为1的路径出来,有一次机会可以沿某条边逆方向走,问最多有多少个点可以被经过?(一个点在路径中无论出现多少正整数次对答案的贡献均为1)

输入

The first line of input contains N and M, giving the number of fields and the number of one-way paths (1 <= N, M <= 100,000). The following M lines each describe a one-way cow path. Each line contains two distinct field numbers X and Y, corresponding to a cow path from X to Y. The same cow path will never appear more than once.

输出

A single line indicating the maximum number of distinct fields Bessie
can visit along a route starting and ending at field 1, given that she can
follow at most one path along this route in the wrong direction.
 

样例输入

7 10
1 2
3 1
2 5
2 4
3 7
3 5
3 6
6 5
7 2
4 7

样例输出

6

题解
   考试的时候调这道题的深搜调了很久,真是没法拯救的运行错误,浪费了很多时间最后还是全部注释掉。凭经验Usaco的题输出样例骗了10分。。。隐约感觉应该用tarjan,虽然前几天才看过但是并没有把握打准确,何况就算缩完点也不知道应该怎么处理。曾几何时做着tarjan的题复习spfa,如今做着综合题复习tarjan和spfa,时间过得多么快啊。
正解思路清晰而实现复杂。输入建原图,用tarjan缩点建出新图和边全部反向的图,点权即为强连通分量中的点数。然后在两个新图中各自从1所属的点跑一遍spfa,得出1到所有点和所有点到1的距离。把强连通分量里的边反向是没有意义的,所以枚举DAG(新图)中的所有边,它联通了一个回路,回路长为起点到1和1到终点的最长路之和。最后要注意的地方,算最长路时把1所在强连通分量计算在内,所以结果中应该除去重复加上的w[c[1]];第二点是如果正反任何一个最长路为0代表它不连通,这样的边是不能记为结果的。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int sj=;
int dfn[sj],low[sj],c[sj],jl[sj],dis[sj],s[sj];
int o[sj],h[sj],l[sj],w[sj];
int m,n,e1,e2,e3,cnt,ge,zh,ans;
bool r[sj];
struct B
{
int v,ne;
}b[sj];
struct BS
{
int u,to,nex;
}bs[sj];
struct BSS
{
int to,nex;
}bss[sj];
inline int re()
{
int jg=,jk=;
jk=getchar()-'';
if(jk>=&&jk<=) jg+=jk;
jk=getchar()-'';
while(jk>=&&jk<=)
{
jg*=;
jg+=jk;
jk=getchar()-'';
}
return jg;
}
void add(int x,int y)
{
b[e1].v=y;
b[e1].ne=h[x];
h[x]=e1++;
}
void ad2(int x,int y)
{
bs[e2].to=y;
bs[e2].nex=l[x];
bs[e2].u=x;
l[x]=e2++;
}
void ad3(int x,int y)
{
bss[e3].to=y;
bss[e3].nex=o[x];
o[x]=e3++;
}
void init()
{
n=re();
m=re();
memset(h,-,sizeof(h));
memset(l,-,sizeof(l));
memset(o,-,sizeof(o));
int a1,a2;
for(int i=;i<=m;i++)
{
a1=re();
a2=re();
add(a1,a2);
}
}
int bj(int x,int y)
{
return x<y?x:y;
}
void spfa1(int x)
{
dis[x]=w[x];
r[x]=;
queue<int> q;
q.push(x);
int f;
while(!q.empty())
{
f=q.front();
for(int i=l[f];i!=-;i=bs[i].nex)
{
if(dis[bs[i].to]<dis[f]+w[bs[i].to])
{
dis[bs[i].to]=dis[f]+w[bs[i].to];
if(r[bs[i].to]!=)
{
q.push(bs[i].to);
r[bs[i].to]=;
}
}
}
r[f]=;
q.pop();
}
}
void spfa2(int x)
{
dis[x]=w[x];
r[x]=;
queue<int> q;
q.push(x);
int f;
while(!q.empty())
{
f=q.front();
for(int i=o[f];i!=-;i=bss[i].nex)
if(dis[bss[i].to]<dis[f]+w[bss[i].to])
{
dis[bss[i].to]=dis[f]+w[bss[i].to];
if(r[bss[i].to]!=)
{
q.push(bss[i].to);
r[bss[i].to]=;
}
}
r[f]=;
q.pop();
}
}
void tarjan(int x)
{
dfn[x]=low[x]=++cnt;
s[++ge]=x;
r[x]=;
for(int i=h[x];i!=-;i=b[i].ne)
{
if(!dfn[b[i].v])
{
tarjan(b[i].v);
low[x]=bj(low[x],low[b[i].v]);
}
else if(r[b[i].v])
low[x]=bj(low[x],dfn[b[i].v]);
}
if(low[x]==dfn[x])
{
int li;
zh++;
do
{
li=s[ge--];
c[li]=zh;
w[zh]++;
r[li]=;
}while(li!=x);
}
}
int db(int &x,int y)
{
x=x>y?x:y;
}
int main()
{
init();
for(int i=;i<=n;i++)
if(!dfn[i])
tarjan(i);
for(int i=;i<=n;i++)
for(int j=h[i];j!=-;j=b[j].ne)
if(c[i]!=c[b[j].v])
{
ad2(c[i],c[b[j].v]);
ad3(c[b[j].v],c[i]);
}
memset(r,,sizeof(r));
memset(dis,,sizeof(dis));
spfa1(c[]);
for(int i=;i<=zh;i++)
jl[i]=dis[i];
memset(r,,sizeof(r));
memset(dis,,sizeof(dis));
spfa2(c[]);
ans=;
for(int i=;i<e2;i++)
if(jl[bs[i].to]&&dis[bs[i].u])
db(ans,jl[bs[i].to]+dis[bs[i].u]-w[c[]]);
printf("%d",ans);
return ;
}
 
 

Grass Cownoisseur[Usaco2015 Jan]的更多相关文章

  1. [补档][Usaco2015 Jan]Grass Cownoisseur

    [Usaco2015 Jan]Grass Cownoisseur 题目 给一个有向图,然后选一条路径起点终点都为1的路径出来,有一次机会可以沿某条边逆方向走,问最多有多少个点可以被经过? (一个点在路 ...

  2. BZOJ3887 [Usaco2015 Jan] Grass Cownoisseur 【tarjan】【DP】*

    BZOJ3887 [Usaco2015 Jan] Grass Cownoisseur Description In an effort to better manage the grazing pat ...

  3. bzoj3887: [Usaco2015 Jan]Grass Cownoisseur

    题意: 给一个有向图,然后选一条路径起点终点都为1的路径出来,有一次机会可以沿某条边逆方向走,问最多有多少个点可以被经过?(一个点在路径中无论出现多少正整数次对答案的贡献均为1) =>有向图我们 ...

  4. [bzoj3887][Usaco2015 Jan]Grass Cownoisseur_trajan_拓扑排序_拓扑序dp

    [Usaco2015 Jan]Grass Cownoisseur 题目大意:给一个有向图,然后选一条路径起点终点都为1的路径出来,有一次机会可以沿某条边逆方向走,问最多有多少个点可以被经过?(一个点在 ...

  5. BZOJ_3887_[Usaco2015 Jan]Grass Cownoisseur_强连通分量+拓扑排序+DP

    BZOJ_3887_[Usaco2015 Jan]Grass Cownoisseur_强连通分量+拓扑排序+DP Description In an effort to better manage t ...

  6. 3890: [Usaco2015 Jan]Meeting Time( dp )

    简单的拓扑图dp.. A(i, j), B(i, j) 表示从点 i 长度为 j 的两种路径是否存在. 用bitset就行了 时间复杂度O(m) --------------------------- ...

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

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

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

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

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

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

随机推荐

  1. 在Linux与Windows上获取当前堆栈信息

    在编写稳定可靠的软件服务时经常用到输出堆栈信息,以便用户/开发者获取准确的运行信息.常用在日志输出,错误报告,异常检测. 在Linux有比较简便的函数获取堆栈信息: #include <stdi ...

  2. Gist - ES6 Iterator

    Introduction Iterator is one of the most common design modes in daily development. Let's explore the ...

  3. svn怎么切换用户

    在使用svn客户端经常会保存用户及密码,方便下次直接登录,有时需要使用别的账号登录,这时该怎么切换呢? 工具/原料 苹果6 小米4 方法/步骤   在使用svn更新或提交数据时需要输入用户名和密码,在 ...

  4. 【Android Developers Training】 6. 配置Action Bar

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  5. Lua性能优化

    原文:Lua Performance Tips 偶然找到<Lua Performance Tips>这篇关于Lua的优化文章,个人认为相较于多数泛泛而谈要好不少.尽管Lua已经到5.2版本 ...

  6. PHP实现简单的评论与回复功能还有删除信息

    我们首先先看一下功能 上面黑色的是评论的下面红色的字体是回复的 再来看看怎么实现的 1.发布评论 <form action="pinglunchili.php" method ...

  7. Bootstrap警告框

    前面的话 在网站中,网页总是需要和用户一起做沟通与交流.特别是当用户操作上下文为用户提供一些有效的警示框,比如说告诉用户操作成功.操作错误.提示或者警告等.在Bootstrap框架有一个独立的组件,实 ...

  8. css自定义动画在微信中无法执行的原因

    这是我去年年底遇到的一个问题, 在这个过程中我发现了一个比较有趣的问题. 我们在做抽奖的时候,微信分享到朋友圈的页面里,安卓机器无法执行页面中的自定义动画(元宝的位移,进入按钮的放大缩小等等).这让我 ...

  9. 以芯片直读方式得到的全盘镜像解析及ext4日志区域解析

    之前在centos中分析了/dev/sda1下的结构,但当对象是一块以芯片直读方式作出来的全盘镜像呢? 这次以安卓手机的全盘镜像为对象,尝试按照ext4文件系统结构手动解析,加强对ext4文件系统.E ...

  10. VB6之ICMP实现ping功能

    代码备忘 'code by lichmama from cnblogs.com Private Type IPAddr ip1 As Byte ip2 As Byte ip3 As Byte ip4 ...