[Usaco2015 Jan]Grass Cownoisseur Tarjan缩点+SPFA
考试的时候忘了缩点,人为dfs模拟缩点,没想到竟然跑了30分,RB爆发。。。
边是可以重复走的,所以在同一个强连通分量里,无论从那个点进入从哪个点出,所有的点一定能被一条路走到。 要使用缩点。
然后我们枚举每一条边,考虑如果将这条边反置的话,就是这条边的终点到1的点的权值(正向的)加上起点到1的点的权值(反向的);例:→→←→→
每个点到1的正向反向距离可以用两遍SPFA解决出来。
先使用tarjan缩点,记录每个点的权值,缩点后权值变为强连通分量中点的个数。缩完点之后重新建图,正向边存1,反向边存-1;
注意:在枚举每一条边求MAX时一定要判断它的起点和终点能否到达1。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
#define pos(i,a,b) for(int i=(a);i<=(b);i++)
#define pos2(i,a,b) for(int i=(a);i>=(b);i--)
#define N 501000
int n,m;
struct haha
{
int next,to,w;
};
haha edgechu[N],edge[N];
int head[N],headchu[N],cnt=1,cntchu=1,cntt,hea;
int belong[N],low[N],dfn[N],ji=1,stack[N],instack[N];
int point[N];
void add(int u,int v,int w)
{
edge[cnt].to=v;
edge[cnt].next=head[u];
edge[cnt].w=w;
head[u]=cnt++;
}
void addchu(int u,int v,int w)
{
edgechu[cntchu].to=v;
edgechu[cntchu].next=headchu[u];
edgechu[cntchu].w=w;
headchu[u]=cntchu++;
}
void tarjan(int now)
{
low[now]=dfn[now]=ji;
ji++;
stack[++hea]=now;
instack[now]=1;
for(int v=headchu[now];v;v=edgechu[v].next)
{
int i=edgechu[v].to;
if(dfn[i]==-1)
{
tarjan(i);
low[now]=min(low[now],low[i]);
}
else
if(instack[i])
low[now]=min(low[now],dfn[i]);
}
if(low[now]==dfn[now])
{
cntt++;
int temp;
while(1)
{
temp=stack[hea--];
belong[temp]=cntt;
point[cntt]++;
instack[temp]=0;
//cout<<"temp="<<temp<<" cntt="<<cntt<<endl;
if(temp==now)
break;
}
}
}
int diszheng[N],disfan[N];
int flag[N];
void spfazheng(int x)
{
queue<int> q;
pos(i,1,n)
diszheng[i]=0;
memset(flag,0,sizeof(flag));
diszheng[x]=point[x];
q.push(x);
flag[x]=1;
int k;
while(!q.empty())
{
k=q.front();
for(int v=head[k];v;v=edge[v].next)
{
int i=edge[v].to;
if(edge[v].w>0&&diszheng[i]<diszheng[k]+point[i])
{
diszheng[i]=diszheng[k]+point[i];
if(!flag[i])
{
q.push(i);
flag[i]=1;
}
}
}
flag[q.front()]=0;
q.pop();
}
}
void spfafan(int x)
{
queue<int> q;
pos(i,1,n)
disfan[i]=0;
memset(flag,0,sizeof(flag));
disfan[x]=point[x];
q.push(x);
flag[x]=1;
int k;
while(!q.empty())
{
k=q.front();
for(int v=head[k];v;v=edge[v].next)
{
int i=edge[v].to;
if(edge[v].w<0&&disfan[i]<disfan[k]+point[i])
{
disfan[i]=disfan[k]+point[i];
if(!flag[i])
{
q.push(i);
flag[i]=1;
}
}
}
flag[q.front()]=0;
q.pop();
}
}
struct qian
{
int from,to;
}cun[N];
int road;
int ans;
int main()
{
//freopen("cown.in","r",stdin);
//freopen("cown.out","w",stdout);
scanf("%d%d",&n,&m);
memset(dfn,-1,sizeof(dfn));
pos(i,1,m)
{
int x,y;
scanf("%d%d",&x,&y);
addchu(x,y,1);
}
pos(i,1,n)
if(dfn[i]==-1)
tarjan(i);
pos(i,1,n)
for(int v=headchu[i];v;v=edgechu[v].next)
{
int j=edgechu[v].to;
if(belong[i]!=belong[j])
{
add(belong[i],belong[j],1);
add(belong[j],belong[i],-1);
cun[++road].from=belong[i];
cun[road].to=belong[j];
}
}
spfafan(belong[1]);spfazheng(belong[1]);
/*pos(i,1,cntt)
cout<<"diszheng[i]="<<diszheng[i]<<" disfan[i]="<<disfan[i]<<endl;*/
pos(i,1,road)
{
if(diszheng[cun[i].to]>0&&disfan[cun[i].from]>0)
ans=max(ans,diszheng[cun[i].to]+disfan[cun[i].from]-point[belong[1]]);
//cout<<"ans="<<ans<<endl;
}
printf("%d",ans);
//while(1);
return 0;
}
[Usaco2015 Jan]Grass Cownoisseur Tarjan缩点+SPFA的更多相关文章
- BZOJ 3887: [Usaco2015 Jan]Grass Cownoisseur tarjan + spfa
Code: #include <bits/stdc++.h> #define setIO(s) freopen(s".in","r",stdin) ...
- BZOJ3887 [Usaco2015 Jan] Grass Cownoisseur 【tarjan】【DP】*
BZOJ3887 [Usaco2015 Jan] Grass Cownoisseur Description In an effort to better manage the grazing pat ...
- [补档][Usaco2015 Jan]Grass Cownoisseur
[Usaco2015 Jan]Grass Cownoisseur 题目 给一个有向图,然后选一条路径起点终点都为1的路径出来,有一次机会可以沿某条边逆方向走,问最多有多少个点可以被经过? (一个点在路 ...
- bzoj3887: [Usaco2015 Jan]Grass Cownoisseur
题意: 给一个有向图,然后选一条路径起点终点都为1的路径出来,有一次机会可以沿某条边逆方向走,问最多有多少个点可以被经过?(一个点在路径中无论出现多少正整数次对答案的贡献均为1) =>有向图我们 ...
- BZOJ 3887/Luogu P3119: [Usaco2015 Jan]Grass Cownoisseur (强连通分量+最长路)
分层建图,反向边建在两层之间,两层内部分别建正向边,tarjan缩点后,拓扑排序求一次1所在强连通分量和1+n所在强联通分量的最长路(长度定义为路径上的强联通分量内部点数和).然后由于1所在强连通分量 ...
- [Usaco2015 Jan]Grass Cownoisseur 图论 tarjan spfa
先缩点,对于缩点后的DAG,正反跑spfa,枚举每条边进行翻转即可 #include<cstdio> #include<cstring> #include<iostrea ...
- BZOJ3887 [Usaco2015 Jan]Grass Cownoisseur[缩点]
首先看得出缩点的套路.跑出DAG之后,考虑怎么用逆行条件.首先可以不用,这样只能待原地不动.用的话,考虑在DAG上向后走,必须得逆行到1号点缩点后所在点的前面,才能再走回去. 于是统计从1号点缩点所在 ...
- 洛谷—— 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 ...
- [bzoj3887][Usaco2015 Jan]Grass Cownoisseur_trajan_拓扑排序_拓扑序dp
[Usaco2015 Jan]Grass Cownoisseur 题目大意:给一个有向图,然后选一条路径起点终点都为1的路径出来,有一次机会可以沿某条边逆方向走,问最多有多少个点可以被经过?(一个点在 ...
随机推荐
- LaTeX初识 新手入门 Texlive和Texmaker学习
转载自:http://blog.sina.com.cn/s/blog_90444ed201016iq6.html http://blog.csdn.net/zb1165048017/article/d ...
- USACO hamming
考试周终于过去了一半,可以继续写USACO了. 先来看一下题目吧. Hamming CodesRob Kolstad Given N, B, and D: Find a set of N codewo ...
- Backbone中父子view之间的值传递
backbone中,使用最多的莫过于在view中进行操作,如模板的渲染以及事件函数的定义.为了提高代码的可维护性,一般地我们会写多个视图即view,将界面按照功能的不同进行模块化划分,模块与view一 ...
- 关于 静态页面布局 中的一些BUG
作为一枚初级程序猿,难免在制作静态页面时会遇到一些BUG,在此,我从网上找了一些资料并且结合自己的项目开发经验,总结了一些在静态页面布局时可能会遇到的问题,希望能对初级程序猿有一定的帮助(资料请参考: ...
- Java泛型概念
1. 概述在引入范型之前,Java类型分为原始类型.复杂类型,其中复杂类型分为数组和类.引入范型后,一个复杂类型就可以在细分成更多的类型.例如原先的类型List,现在在细分成List<Objec ...
- 计算机浏览器存储技术cookie、sessionStorage、localStorage
HTTP无状态协议是指协议对于事务处理没有记忆能力.会话跟踪协议的状态是指下一次传输可以"记住"这次传输信息的能力,无状态是指同一个会话(注意什么叫同一个会话)的连续两个请求互相不 ...
- Matlab: 白噪声与曲线拟合
在信号处理中常常需要用到曲线拟合,这里介绍一下利用最小二乘拟合一般曲线的方法,并对滤掉信号中白噪声的方法作些介绍. 为了测试拟合算法的好坏,先模拟出一个信号作为检验算法的例子: 用白噪声产生模拟信号: ...
- 为实施了IFD的Dynamics 365更换自签名的SSL证书以符合Chrome的要求
关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复259或者20170704可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong. ...
- Unity strip engine code可能会使程序崩溃
最近正在做新大厅的红包推荐口令快速领金币入口拍卖行之类的功能,同事把我的捕鱼整合到他的项目中时出现了闪退的问题,经排查是因为strip engine code选项. Strip engine code ...
- DL4NLP——词表示模型(一)表示学习;syntagmatic与paradigmatic两类模型;基于矩阵的LSA和GloVe
本文简述了以下内容: 什么是词表示,什么是表示学习,什么是分布式表示 one-hot representation与distributed representation(分布式表示) 基于distri ...