[Usaco2015 Jan]Grass Cownoisseur

题目

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

INPUT

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.
N个点,M条有向边,无重边

OUTPUT

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.

SAMPLE

INPUT

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

OUTPUT

6

解题报告

这道题考试的时候,一看就知道是tarjan,然后就真的傻傻的打了个tarjan+dfs,就A了一个点= =
正解:
tarjan缩点,因为可以逆转一条边,而同一强连通分量里的边逆转是没啥用的,所以我们可以枚举缩点后的边。
首先,跑2遍SPFA,一遍缩点后的正边,一遍反边,处理出正反两个最大的经过权值(每点权值为缩点后强连通分量的点数)。
剩下的就很简单了,思考当一条有向边反过来时,它反边的起点走的是正向的最大权值,而终点则走的是反向的最大权值,那么我们枚举每一条边,两权相加求max即为答案。
注意:特判,两边SPFA若有一遍没有联通这条边对应的强连通分量,这个点就不能跑。
 #include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
inline int read(){
int sum();
char ch(getchar());
while(ch<''||ch>'')
ch=getchar();
while(ch>=''&&ch<=''){
sum=sum*+ch-'';
ch=getchar();
}
return sum;
}
struct edge{
int s,e,n;
}k[],a[],b[];
int pre[],tot;
inline void insert(int s,int e){
k[++tot].s=s;
k[tot].e=e;
k[tot].n=pre[s];
pre[s]=tot;
}
int low[],dfn[],stack[],bl[],size[];
int head,cnt,qlt;
bool vis[];
inline int my_min(int a,int b){
return a<b?a:b;
}
inline int my_max(int a,int b){
return a>b?a:b;
}
inline void tarjan(int u){
low[u]=dfn[u]=++cnt;
vis[u]=;
stack[++head]=u;
for(int i=pre[u];i!=-;i=k[i].n){
int e(k[i].e);
if(!dfn[e]){
tarjan(e);
low[u]=my_min(low[u],low[e]);
}
else
if(vis[e])
low[u]=my_min(low[u],dfn[e]);
}
if(low[u]==dfn[u]){
int tmp;
qlt++;
while(){
tmp=stack[head--];
bl[tmp]=qlt;
vis[tmp]=;
if(tmp==u)
break;
}
}
}
int adj[],num;
inline void add(int s,int e){
a[++num].s=s;
a[num].e=e;
a[num].n=adj[s];
adj[s]=num;
}
queue<int>q;
int fz[];
inline void spfa1(int x){
memset(vis,,sizeof(vis));
memset(fz,,sizeof(fz));
q.push(x);
fz[x]=size[x];
vis[x]=;
while(!q.empty()){
int k(q.front());
q.pop();
for(int i=adj[k];i!=-;i=a[i].n){
int e(a[i].e);
if(fz[e]<fz[k]+size[e]){
fz[e]=fz[k]+size[e];
if(!vis[e]){
q.push(e);
vis[e]=;
}
}
}
vis[k]=;
}
}
int hhh,nxt[];
inline void init(int s,int e){
b[++hhh].s=s;
b[hhh].e=e;
b[hhh].n=nxt[s];
nxt[s]=hhh;
}
int ff[];
inline void spfa2(int x){
memset(vis,,sizeof(vis));
memset(ff,,sizeof(ff));
q.push(x);
ff[x]=size[x];
vis[x]=;
while(!q.empty()){
int k(q.front());
q.pop();
for(int i=nxt[k];i!=-;i=b[i].n){
int e(b[i].e);
if(ff[e]<ff[k]+size[e]){
ff[e]=ff[k]+size[e];
if(!vis[e]){
q.push(e);
vis[e]=;
}
}
}
vis[k]=;
}
}
inline int find(int x){
int s(a[x].e),e(a[x].s);
if(!fz[s]||!ff[e])
return ;
return fz[s]+ff[e]-size[bl[]];
}
int n,m;
int main(){
memset(pre,-,sizeof(pre));
memset(adj,-,sizeof(adj));
memset(nxt,-,sizeof(nxt));
n=read(),m=read();
for(int i=;i<=m;i++){
int x(read()),y(read());
insert(x,y);
}
for(int i=;i<=n;i++)
if(!dfn[i])
tarjan(i);
for(int i=;i<=n;i++)
size[bl[i]]++;
for(int i=;i<=tot;i++){
int s(k[i].s),e(k[i].e);
if(bl[s]!=bl[e])
add(bl[s],bl[e]),init(bl[e],bl[s]);
}
spfa1(bl[]);
spfa2(bl[]);
int ans();
for(int i=;i<=num;i++)
ans=my_max(ans,find(i));
printf("%d\n",ans);
}
ps:调了我两个小时,最后发现重新建边的时候我用的原来点的编号,没有用缩完点后的编号,然后就听取蛙声一片了= =

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

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

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

  2. bzoj3887: [Usaco2015 Jan]Grass Cownoisseur

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

  3. 洛谷—— 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 ...

  4. [Usaco2015 Jan]Grass Cownoisseur Tarjan缩点+SPFA

    考试的时候忘了缩点,人为dfs模拟缩点,没想到竟然跑了30分,RB爆发... 边是可以重复走的,所以在同一个强连通分量里,无论从那个点进入从哪个点出,所有的点一定能被一条路走到. 要使用缩点. 然后我 ...

  5. [Usaco2015 Jan]Grass Cownoisseur 图论 tarjan spfa

    先缩点,对于缩点后的DAG,正反跑spfa,枚举每条边进行翻转即可 #include<cstdio> #include<cstring> #include<iostrea ...

  6. BZOJ 3887/Luogu P3119: [Usaco2015 Jan]Grass Cownoisseur (强连通分量+最长路)

    分层建图,反向边建在两层之间,两层内部分别建正向边,tarjan缩点后,拓扑排序求一次1所在强连通分量和1+n所在强联通分量的最长路(长度定义为路径上的强联通分量内部点数和).然后由于1所在强连通分量 ...

  7. BZOJ3887 [Usaco2015 Jan]Grass Cownoisseur[缩点]

    首先看得出缩点的套路.跑出DAG之后,考虑怎么用逆行条件.首先可以不用,这样只能待原地不动.用的话,考虑在DAG上向后走,必须得逆行到1号点缩点后所在点的前面,才能再走回去. 于是统计从1号点缩点所在 ...

  8. BZOJ 3887: [Usaco2015 Jan]Grass Cownoisseur tarjan + spfa

    Code: #include <bits/stdc++.h> #define setIO(s) freopen(s".in","r",stdin) ...

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

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

随机推荐

  1. JAVAEE——spring01:介绍、搭建、概念、配置详解、属性注入和应用到项目

    一.spring介绍 1.三层架构中spring位置 2.spring一站式框架 正是因为spring框架性质是属于容器性质的. 容器中装什么对象就有什么功能.所以可以一站式. 不仅不排斥其他框架,还 ...

  2. 百度地图 js api 实现 line 居中显示

    项目中有个需求需要在百度地图的中心显示画的线,以前用过mapPanto这个方法,传入坐标就可以将地图平移到这个坐标,不过不知道如何获取线的中心点,看了别人的代码,有以下两个函数可以实现这个功能 get ...

  3. MyEclipse常用操作

    选择你要注释的那一行或多行代码,按Ctrl+/即可,取消注释也是选中之后按Ctrl+/即可. 如果你想使用的快捷键的注释是的话,那么你的快捷键是ctrl+shift+/我以前都是手动注释的,直接打// ...

  4. win 10 开机后无法显示桌面

    我整理了几种方法,可以试一下 1> win + x 然后运行explorer.exe 2> 1/// shift + ctrl + esc 进入 任务管理器 2///        点击 ...

  5. html路径问题

     1.绝对路径     绝对路径是指文件在硬盘上真正存在的路径.例如"bg.jpg"这个图片是存放在硬盘的"E:\book\网页布局代码\第2章"目录下,那么 ...

  6. touchmover 手机端拖动方法

    function drag(obj, parentNode) { var obj = document.getElementById(obj); if (arguments.length == 1) ...

  7. Scrapy爬虫实例教程(二)---数据存入MySQL

    书接上回 实例教程(一) 本文将详细描述使用scrapy爬去左岸读书所有文章并存入本地MySql数据库中,文中所有操作都是建立在scrapy已经配置完毕,并且系统中已经安装了Mysql数据库(有权限操 ...

  8. jdk和jre有什么区别?

    简单的说JDK是面向开发人员使用的SDK,它提供了Java的开发环境和运行环境.SDK是Software Development Kit 一般指软件开发包,可以包括函数库.编译程序等. JDK就是Ja ...

  9. [CF161D]Distance in Tree-树状dp

    Problem Distance in tree 题目大意 给出一棵树,求这棵树上有多少个最短距离为k的点对. Solution 这个题目可以用点分治来做,然而我到现在还是没有学会点分治,所以只好用树 ...

  10. 集合的定义,操作及运算 (Python)

    集合的定义: 集合和列表([  ]) 与  字典 ( {    }) 不同,没有特别的特别的语法格式.可以使用set () 创建. 集合同字典一样是无序的.也是不具有重复性的.因此可以把列表变成集合进 ...