我们可以看出这个东西可以缩点成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. Dynamics 365-下载新版本的开发工具

    可以使用下面的Powershell脚本在NuGet下載最新的CRM开发工具.这些工具包括: Tool NuGet Package Code generation tool CrmSvcUtil.exe ...

  2. python构造二维列表以及排序字典

    1. 构造二维列表: 比如我现在需要一个100*100的二维列表: a = [] for i in range(100): a.append([]) for j in range(100): a[i] ...

  3. vue笔记 介绍及安装 一

    Vue.js 是什么 Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架.与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用.Vue 的核心库只关注视图层, ...

  4. 素数环 南阳acm488(回溯法)

    素数环 时间限制:1000 ms  |  内存限制:65535 KB 难度:2   描述 有一个整数n,把从1到n的数字无重复的排列成环,且使每相邻两个数(包括首尾)的和都为素数,称为素数环. 为了简 ...

  5. Windows Store App下代码加载page resource和resw文件里的string

    加载page resource 在page的code behind里: this.Resources["textBoxStyle"] 加载resw文件里的string: Resou ...

  6. kafka集群部署文档(转载)

    原文链接:http://www.cnblogs.com/luotianshuai/p/5206662.html Kafka初识 1.Kafka使用背景 在我们大量使用分布式数据库.分布式计算集群的时候 ...

  7. 【转】Django添加静态文件设置

    STATIC_URL = '/statics/'STATIC_ROOT= os.path.join(BASE_DIR, 'statics')STATICFILES_DIRS = ( os.path.j ...

  8. 2016年JD工作遇到的问题:1-5,搭建环境和熟悉项目过程中的坑

    1.更新不需要权限的项目A,却提示没有权限. 先从Git上更新项目A的代码,提示没有权限. 然后从Git上更新其它项目B的代码,正常. 再更新项目A的代码,正常了. 奇葩问题! 2.Eclipse中, ...

  9. ArrayMap java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Object[]

    错误堆栈: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Object[] at android ...

  10. 位运算 & 网络序字节序

    一.初识位运算 位运算,见词明意,二进制运算,通常需要将运算数转换为二进制再进行处理,如果是在程序语言中则无需自己进行进制转换,基本的位操作符有如下几种:与(&).或(|).异或(^).取反( ...