[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. javaScript的一些奇妙动画

         今天我给大家讲一下JavaScript中的显示隐藏.淡入淡出的效果 显示与隐藏动画效果 show()方法: show()方法会动态地改变当前元素的高度.宽度和不透明度,最终显示当前元素,此时 ...

  2. 解密SuperWebview的一种另类方法

    解密SuperWebview的一种另类方法 什么是SuperWebview SuperWebview是APICloud官方推出的另一项重量级API生态产品,以SDK方式提供,致力于提升和改善移动设备W ...

  3. jquery的几个国内CDN加速节点

    分享几个jquery的几个国内国外的CDN加速节点,方便广大的开发设计者调用和节约空间,官网的总是最新版本的jquery所以不用去担心版本更新问题,其他加速节点可能不会在更新版本,所以取舍问题自己决定 ...

  4. Administrator账户密码忘了怎么办

    WIN7的Administrator账户密码忘了怎么办   1.准备一个带有winpe系统的系统光盘或者U盘 2.启动电脑,按F12选择U盘或者光盘启动,进入winpe操作系统 3.找到c:\wind ...

  5. [leetcode-507-Perfect Number]

    We define the Perfect Number is a positive integer that is equal to the sum of all its positive divi ...

  6. 【Android Developers Training】 62. 搭建一个OpenGL ES环境

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

  7. hadoop伪分布式环境搭建

    环境:Centos6.9+jdk+hadoop1.下载hadoop的tar包,这里以hadoop2.6.5版本为例,下载地址https://archive.apache.org/dist/hadoop ...

  8. MyBatis-sql映射文件

    Sql映射文件 MyBatis真正的力量是在映射语句中.这里是奇迹发生的地方.对于所有的力量,SQL映射的XML文件是相当的简单.当然如果你将它们和对等功能的JDBC代码来比较,你会发现映射文件节省了 ...

  9. 一次C++调试记录

         之前开发用Linux C比较多,C++中的STL 容器基本没有接触过.最近在学习C++,平时用到c++ 17中的部分新特性,下面就简单分享下自己C++的学习流程. 一.环境搭建      本 ...

  10. vue.js 组件之间传递数据

    前言 组件是 vue.js 最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用.如何传递数据也成了组件的重要知识点之一. 组件 组件与组件之间,还存在着不同的关 ...