【tarjan+拓扑】BZOJ3887-[Usaco2015 Jan]Grass Cownoisseur
【题目大意】
给一个有向图,然后选一条路径起点终点都为1的路径出来,有一次机会可以沿某条边逆方向走,问最多有多少个点可以被经过?(一个点在路径中无论出现多少正整数次对答案的贡献均为1)
【思路】
首先缩点,对于每一个联通块求出正图和反图中节点1所在的联通块到它的最长节点数。这个用拓扑排序处理一下。
枚举每一条边取反,对于边(u,v),其取反后的距离就等于dis[u所在的联通快]+dis[v所在的联通块]-dis[1所在的联通块](因为会被重复计算不要忘记减去)
我一开始非常脑抽地在想会不会发生这样的情况:本来到u所在的联通块就会经过v,这样不就重复计算点了。要注意缩点之后的图为DAG,如果存在v->u的路径,同时存在u->v的路径,那么必定存在环,矛盾。
【错误点】
写x节点所在的联通块的时候,一直写成x节点。千万不要忘记了col[]。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
const int MAXN=+;
vector<int> E[MAXN];
vector<int> tE[MAXN],rtE[MAXN];
stack<int> S;
int x[MAXN],y[MAXN];
int instack[MAXN],low[MAXN],dfn[MAXN],col[MAXN],size[MAXN],cnt,colcnt;
int dis[MAXN],rdis[MAXN],degree1[MAXN],degree2[MAXN];
int vis[MAXN];
int n,m; void Topology1()
{
memset(dis,0xef,sizeof(dis));//初始化为-INF
queue<int> que;
dis[col[]]=size[col[]];
for (int i=;i<=colcnt;i++)
if (!degree1[i]) que.push(i);
while (!que.empty())
{
int now=que.front();que.pop();
for (int i=;i<tE[now].size();i++)
{
int to=tE[now][i];
dis[to]=max(dis[to],dis[now]+size[to]);
if (!--degree1[to]) que.push(to);
}
}
} void Topology2()
{
memset(rdis,0xef,sizeof(rdis));
queue<int> que;
rdis[col[]]=size[col[]];
for (int i=;i<=colcnt;i++)
if (!degree2[i]) que.push(i);
while (!que.empty())
{
int now=que.front();que.pop();
for (int i=;i<rtE[now].size();i++)
{
int to=rtE[now][i];
rdis[to]=max(rdis[to],rdis[now]+size[to]);
if (!--degree2[to]) que.push(to);
}
}
} void tarjan(int u)
{
dfn[u]=low[u]=++cnt;
instack[u]=;
S.push(u);
for (int i=;i<E[u].size();i++)
{
int v=E[u][i];
if (!instack[v])
{
tarjan(v);
low[u]=min(low[u],low[v]); }
else if (instack[v]==) low[u]=min(low[u],dfn[v]);
} if (dfn[u]==low[u])
{
colcnt++;
int x;
do
{
x=S.top();
col[x]=colcnt;
instack[x]=;
size[colcnt]++;
S.pop();
}while (x!=u);
}
} void init()
{
scanf("%d%d",&n,&m);
for (int i=;i<m;i++)
{
scanf("%d%d",&x[i],&y[i]);
E[x[i]].push_back(y[i]);
}
memset(instack,,sizeof(instack));
cnt=colcnt=;
for (int i=;i<=n;i++)
if (!instack[i]) tarjan(i);
for (int i=;i<m;i++)
{
if (col[x[i]]!=col[y[i]])
{
tE[col[x[i]]].push_back(col[y[i]]);
degree1[col[y[i]]]++;
rtE[col[y[i]]].push_back(col[x[i]]);
degree2[col[x[i]]]++;
}
}
} void solve()
{
memset(dis,,sizeof(dis));
memset(rdis,,sizeof(rdis));
Topology1();
Topology2();
int ans=-;
for (int i=;i<m;i++)
{
ans=max(ans,dis[col[x[i]]]+rdis[col[y[i]]]);//注意这里是col[x[i]]不要写成x[i]了
ans=max(ans,rdis[col[x[i]]]+dis[col[y[i]]]);
}
printf("%d",ans-size[]);
} int main()
{
init();
solve();
return ;
}
【tarjan+拓扑】BZOJ3887-[Usaco2015 Jan]Grass Cownoisseur的更多相关文章
- BZOJ3887 [Usaco2015 Jan] Grass Cownoisseur 【tarjan】【DP】*
BZOJ3887 [Usaco2015 Jan] Grass Cownoisseur Description In an effort to better manage the grazing pat ...
- bzoj3887: [Usaco2015 Jan]Grass Cownoisseur
题意: 给一个有向图,然后选一条路径起点终点都为1的路径出来,有一次机会可以沿某条边逆方向走,问最多有多少个点可以被经过?(一个点在路径中无论出现多少正整数次对答案的贡献均为1) =>有向图我们 ...
- BZOJ3887 [Usaco2015 Jan]Grass Cownoisseur[缩点]
首先看得出缩点的套路.跑出DAG之后,考虑怎么用逆行条件.首先可以不用,这样只能待原地不动.用的话,考虑在DAG上向后走,必须得逆行到1号点缩点后所在点的前面,才能再走回去. 于是统计从1号点缩点所在 ...
- [bzoj3887][Usaco2015 Jan]Grass Cownoisseur_trajan_拓扑排序_拓扑序dp
[Usaco2015 Jan]Grass Cownoisseur 题目大意:给一个有向图,然后选一条路径起点终点都为1的路径出来,有一次机会可以沿某条边逆方向走,问最多有多少个点可以被经过?(一个点在 ...
- [补档][Usaco2015 Jan]Grass Cownoisseur
[Usaco2015 Jan]Grass Cownoisseur 题目 给一个有向图,然后选一条路径起点终点都为1的路径出来,有一次机会可以沿某条边逆方向走,问最多有多少个点可以被经过? (一个点在路 ...
- [Usaco2015 Jan]Grass Cownoisseur Tarjan缩点+SPFA
考试的时候忘了缩点,人为dfs模拟缩点,没想到竟然跑了30分,RB爆发... 边是可以重复走的,所以在同一个强连通分量里,无论从那个点进入从哪个点出,所有的点一定能被一条路走到. 要使用缩点. 然后我 ...
- [Usaco2015 Jan]Grass Cownoisseur 图论 tarjan spfa
先缩点,对于缩点后的DAG,正反跑spfa,枚举每条边进行翻转即可 #include<cstdio> #include<cstring> #include<iostrea ...
- BZOJ 3887: [Usaco2015 Jan]Grass Cownoisseur tarjan + spfa
Code: #include <bits/stdc++.h> #define setIO(s) freopen(s".in","r",stdin) ...
- BZOJ 3887/Luogu P3119: [Usaco2015 Jan]Grass Cownoisseur (强连通分量+最长路)
分层建图,反向边建在两层之间,两层内部分别建正向边,tarjan缩点后,拓扑排序求一次1所在强连通分量和1+n所在强联通分量的最长路(长度定义为路径上的强联通分量内部点数和).然后由于1所在强连通分量 ...
随机推荐
- Spring Boot中使用Spring-data-jpa让数据访问更简单、更优雅
在上一篇Spring中使用JdbcTemplate访问数据库中介绍了一种基本的数据访问方式,结合构建RESTful API和使用Thymeleaf模板引擎渲染Web视图的内容就已经可以完成App服务端 ...
- 75.VS2013和opencv3.1.0开发环境配置
首先要做的就是 开发环境配置,具体过程如下: Step 1:OpenCV环境变量配置 我的电脑--->属性--->高级系统设置--->高级--->环境变量--->系统变量 ...
- Linux内核多线程实现方法 —— kthread_create函数【转】
转自:http://blog.csdn.net/sharecode/article/details/40076951 Linux内核多线程实现方法 —— kthread_create函数 内核经常需要 ...
- 安全测试===dos攻击和ddos攻击
Dos攻击: dos攻击是Denial of Service的简称,即拒绝服务,造成DoS的攻击行为被称为DoS攻击,其目的是使计算机或网络无法提供正常的服务 DoS攻击是指故意的攻击网络协议实现的缺 ...
- http 错误代码解释 && nginx 自定义错误【转】
如果向您的服务器发出了某项请求要求显示您网站上的某个网页(例如,当用户通过浏览器访问您的网页或在 Googlebot 抓取该网页时),那么,您的服务器会返回 HTTP 状态代码以响应该请求. 此状态代 ...
- 前端nginx时,让后端tomcat记录真实IP【转】
对于nginx+tomcat这种架构,如果后端tomcat配置保持默认,那么tomcat的访问日志里,记录的就是前端nginx的IP地址,而不是真实的访问IP.因此,需要对nginx.tomcat做如 ...
- Android检测富文本中的<img标签并实现点击效果
本文旨在:通过点击一张图片Toast输出位置与url链接. 闲话少说,实现原理大概是酱紫的::通过正则表达式检测富文本内的图片集合并获取url,在src=“xxx” 后面添加 onclick方法,至于 ...
- shell脚本执行方式
# BY THE WAY, 其实这块内容算是比较简单的,但是都比较常记得它最基本的两种方式,另外两种却忘记了 1. 利用sh或bash命令执行 sh test.sh bash test.sh 2. 在 ...
- UBuntu14.04 --vim安装YouCompleteMe插件
说明 我电脑的系统参数(用 uname -a命令查看)如下: Linux avyn-Lenovo --generic #-Ubuntu SMP Tue Mar :: UTC i686 i686 i68 ...
- Effective C++笔记(五):实现
参考:http://www.cnblogs.com/ronny/p/3754755.html 条款26:尽可能延后变量定义式的出现时间 有些对象,你可能过早的定义它,而在代码执行的过程中发生了导常,造 ...