我们可以看出这个东西可以缩点成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. mysql5.6主主复制及keepalived 高可用

    1.实验目的 mysql服务器作为生产环境中使用最广泛的数据库软件,以其开源性,稳定性而广泛使用,但同时由于数据存储,读写频率高,极易造成数据库出错,从而给企业造成不可挽回的损失,我们除了做好数据库的 ...

  2. unity独立游戏开发日志2018/09/22

    f::很头痛之前rm做的游戏在新电脑工程打不开了...只能另起炉灶... 还不知道新游戏叫什么名...暂且叫方块世界.(素材已经授权) 首先是规划下场景和素材文件夹的建立. unity常用的文件夹有: ...

  3. R语言绘图:箱线图

    使用ggplot2绘制箱线图 ######*****绘制箱线图代码*****####### data1$学区房 <- factor(data1$school, levels = 0:1, lab ...

  4. 39-Role以及Claims授权

    asp.net core多鼓励使用claims授权 1-使用role授权 在类或方法上贴上Roles,这样就知道有user的角色才可以访问 [Authorize(Roles="user&qu ...

  5. python基础之进程间通信、进程池、协程

    进程间通信 进程彼此之间互相隔离,要实现进程间通信(IPC),multiprocessing模块支持两种形式:队列和管道,这两种方式都是使用消息传递的. 进程队列queue 不同于线程queue,进程 ...

  6. PHP.46-TP框架商城应用实例-后台21-权限管理-权限和角色的关系

    权限和角色的关系 权限功能 角色功能 权限与角色的关联要通过权限-角色表进行{多对多} /********* 角色-权限表 *********/ drop if exists p39_role_pri ...

  7. ASP.NET MVC文件上传【转】

    最近用到了文件上传功能,下面给出ASP.NET MVC文件上传的一个简单示例: 一.前端代码 @using (Html.BeginForm("UploadFile", " ...

  8. 使用Entity Framework出错

          在使用的过程中,写了一个例子,结果就报错说      The context cannot be used while the model is being created.      在 ...

  9. C++学习011-常用内存分配及释放函数

    C++用有多种方法来分配及释放内存,下面是一些经常使用的内存分配及释放函数 现在我还是一个技术小白,一般用到也指示 new+delete 和 malloc和free 其他的也是在学习中看到,下面的文字 ...

  10. LeetCode 25 —— K 个一组翻转链表

    1. 题目 2. 解答 首先,利用快慢指针确定链表的总结点数. 偶数个结点时,结点个数等于 i * 2. 奇数个结点时,结点个数等于 i * 2 + 1. 然后将链表的每 K 个结点划分为一组.循环对 ...