我们可以看出这个东西可以缩点成DAG,因为我们在所称的点里用特技的话,要么没用,要么削弱自己对点的收割能力与边的联通权,所以我们缩完点之后在图上枚举反向的变,因为我们只可能反向一条边,而且我们知道在这条边上走的方向,那么我们一定是在边终点回去,在边起点来,因为一来一回的这两条路径一定没有交叉所以我们找着两条路径的最大值,我们跑两边SPFA就好了,(一边正向,一边反向)。

注意在无向图Tarjan时要穷举,因为一个点可能走不完。

#include<cstdio>
#include<cstring>
#include<iostream>
#define MAXN 100005
using namespace std;
inline int read()
{
int sum=;
char ch=getchar();
while(ch<''||ch>'')ch=getchar();
while(ch>=''&&ch<='')
{
sum=(sum<<)+(sum<<)+ch-'';
ch=getchar();
}
return sum;
}
inline int Min(int x,int y)
{
return x<y?x:y;
}
inline int Max(int x,int y)
{
return x>y?x:y;
}
int dfn[MAXN],low[MAXN],when,stack[MAXN],top;
struct Tr
{
int to,next,w;
}C[MAXN],c[MAXN<<];
int Head[MAXN],T,head[MAXN],t;
bool in[MAXN];
inline void Add(int x,int y)
{
C[++T].to=y;
C[T].next=Head[x];
Head[x]=T;
}
int belong[MAXN],sum[MAXN],num;
int n,m;
void Tarjan(int x)
{
low[x]=dfn[x]=++when;
stack[++top]=x;
in[x]=;
for(int i=Head[x];i;i=C[i].next)
{
int y=C[i].to;
if(!dfn[y])
{
Tarjan(y);
low[x]=Min(low[x],low[y]);
}
else if(in[y])
low[x]=Min(low[x],dfn[y]);
}
if(dfn[x]==low[x])
{
int j;
num++;
do
{
j=stack[top--];
in[j]=;
belong[j]=num;
sum[num]++;
}while(j!=x);
}
}
inline void add(int x,int y,int z)
{
c[++t].to=y;
c[t].next=head[x];
head[x]=t;
c[t].w=z;
}
struct E
{
int x,y;
}e[MAXN];
int sz;
inline void buildnew()
{
for(int x=;x<=n;x++)
{
for(int i=Head[x];i;i=C[i].next)
{
int y=C[i].to;
if(belong[x]==belong[y])continue;
e[++sz].x=belong[x];
e[sz].y=belong[y];
add(belong[x],belong[y],);
add(belong[y],belong[x],);
}
}
}
int S,q[MAXN],tail,dis_to[MAXN],dis_from[MAXN];
void spfa1()
{
memset(dis_from,-,sizeof(dis_from));
dis_from[S]=;
q[]=S;
top=tail=;
in[S]=;
while(top<=tail)
{
int x=q[top++];
in[x]=;
for(int i=head[x];i;i=c[i].next)
if(c[i].w==)
{
if(dis_from[x]+sum[c[i].to]>dis_from[c[i].to])
{
dis_from[c[i].to]=dis_from[x]+sum[c[i].to];
if(!in[c[i].to])
in[c[i].to]=,q[++tail]=c[i].to;
}
}
}
}
void spfa2()
{
memset(dis_to,-,sizeof(dis_to));
q[]=S;
top=tail=;
dis_to[S]=sum[S];
in[S]=;
while(top<=tail)
{
int x=q[top++];
in[x]=;
for(int i=head[x];i;i=c[i].next)
if(c[i].w)
{
if(dis_to[x]+sum[c[i].to]>dis_to[c[i].to])
{
dis_to[c[i].to]=dis_to[x]+sum[c[i].to];
if(!in[c[i].to])
in[c[i].to]=,q[++tail]=c[i].to;
}
}
}
}
inline void Init()
{
n=read(),m=read();
for(int i=;i<=m;i++)
{
int x=read(),y=read();
Add(x,y);
}
for(int i=;i<=n;i++)
if(!dfn[i])
Tarjan(i);
buildnew();
S=belong[];
spfa1();
spfa2();
}
int ans;
inline void work()
{
ans=sum[S];
for(int i=;i<=sz;i++)
{
int x=e[i].y,y=e[i].x;
if(dis_to[x]==-||dis_from[y]==-)continue;
ans=Max(ans,dis_to[x]+dis_from[y]);
}
printf("%d",ans);
}
int main()
{
Init();
work();
return ;
}

【BZOJ3887】【Usaco2015 Jan】Grass Cownoisseur Tarjan+Spfa的更多相关文章

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

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

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

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

  3. bzoj 3887: Grass Cownoisseur Tarjan+Topusort

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

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

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

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

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

  6. 【题解】洛谷P3119 Grass Cownoisseur G

    题面:洛谷P3119 Grass Cownoisseur G 本人最近在熟悉Tarjan的题,刷了几道蓝题后,我飘了 趾高气扬地点开这道紫题,我一瞅: 哎呦!这不是分层图吗? 突然就更飘了~~~ 用时 ...

  7. 【Python】【容器 | 迭代对象 | 迭代器 | 生成器 | 生成器表达式 | 协程 | 期物 | 任务】

    Python 的 asyncio 类似于 C++ 的 Boost.Asio. 所谓「异步 IO」,就是你发起一个 IO 操作,却不用等它结束,你可以继续做其他事情,当它结束时,你会得到通知. Asyn ...

  8. 【Python】【面向对象】

    """# [[面向对象]]#[访问限制]#如果要让内部属性不被外部访问,可加双下划线,编程私有变量.只有内部可以访问,外部不能访问.class Student(objec ...

  9. 【Ruby】【基础】

    # [Ruby 块]=begin1 块由大量代码构成2 块中代码包含在{}内3 从与其相同名称的函数调用4 可以使用yield语句调用块=enddef test p '在test方法内' yield ...

随机推荐

  1. linux中安装node

    1.去官网下载和自己系统匹配的文件: 英文网址:https://nodejs.org/en/download/ 中文网址:http://nodejs.cn/download/ 通过 uname -a ...

  2. zabbix使用iostat命令参数监控磁盘性能

    iostat命令 先说一个坑把,在开始监控的时候使用命令iostat -dtkx,得到的结果看上去没问题,但是在web监控窗口数据就说不变动,为啥呢,因为iostat这个命令得到的第一个数据始终是磁盘 ...

  3. 模块导入应用settings的字符串

    看django源码,感觉他的settings好高大上然后自己试试 以上是文件目录 email.py中代码 class Email: def send(self): print('发送email') M ...

  4. ruby Dir类

    类方法 1. Dir[pat]    Dir::glob( pat) 返回一个数组,包含与指定的通配符模式 pat 匹配的文件名: * - 匹配包含 null 字符串的任意字符串 ** - 递归地匹配 ...

  5. ruby 数据类型Symbol

    一.符号创建 符号是Symbol类的实例,使用冒号加一个标识符即可创建符号 :a :"This is a symno" 二.符号字符串相互转换 p :symbol.to_s #=& ...

  6. R语言学习笔记(十六):构建分割点函数

    选取预测概率的分割点 cutoff<- function(n,p){ pp<-1 i<-0 while (pp>=0.02) { model.predfu<-rep(&q ...

  7. 【转】已有打开的与此 Command 相关联的 DataReader,必须首先将它关闭

    在运用Linq to sql 或者 linq to entity等相关linq技术进行数据库访问操作时,如果发生上述异常是因为是因为.NET內部是使用DataReader作数据存取,DataReade ...

  8. LINQ查询操作符

    ·First - 返回集合中的第一个元素:不延迟 ·FirstOrDefault - 返回集合中的第一个元素(如果没有则返回默认值):不延迟 ·Last - 返回集合中的最后一个元素:不延迟 ·Las ...

  9. 3124: [Sdoi2013]直径

    3124: [Sdoi2013]直径 https://www.lydsy.com/JudgeOnline/problem.php?id=3124 分析: 所有直径都经过的边,一定都是连续的一段.(画个 ...

  10. 不同编译器下,定义一个地址按x字节对齐的数组

    以前一直用MDK,用__align(4)就可以定义一个首地址被4整除.地址按4字节对齐的数组,但今天用IAR发现这么写编译报错. 搜了一下才发现,原来不同的编译器,需要用不同的表达方式: #if de ...