题面:洛谷P3119 Grass Cownoisseur G

本人最近在熟悉Tarjan的题,刷了几道蓝题后,我飘了

趾高气扬地点开这道紫题,我一瞅:

哎呦!这不是分层图吗?

突然就更飘了~~~

用时20min写了一个分层图+bfs上去,却看到了一片红......

我:????

苦(查)思(看)冥(题)想(解)后,我恍然大悟

我好像忘了比较大小了(→_→)

改了改,提交上去,果然A了~~~

下面进入正题:

大约的问题就是:已知有n个点,m条有向边,问从1点出发,最后回到1点,可以逆行一次,最多能到达几个点?(每个点可以经过多次)

(语文不好请别介意)

这个题如果只是从1点出发,最多能到几个点最后回到1点的话,那一个bfs就解决了

但是,既然有逆行一次,我们可以再建一层图当做是分层图中的一次优惠来做(具体可以看我的上一篇文

然后用spfa(或bfs)通过tarjan缩点来维护点权

好,既然这样,这个题的解法大概就出来了:

分层图+tarjan+bfs(spfa)

下面上伪代码:

for (int i = 1; i <= n; i++){
for (int j = head[i]; j; j = e[j].nxt){//遍历边
v = e[j].v;
if (num[i] != num[v]){//判断这个边缩点后是否存在
add(num[i], num[v]);
add(num[v], num[i] + g);//将上一层v点与下一层u连接
add(num[i] + g, num[v] + g);
}//建分层图
}
}

假如有一条通过tarjan缩点后依然存在的边:从u点到v点

然后建分层图,将上一层的v点连接到下一点的u点(模拟逆行)

然后求从第一层的1点到第二层的1点最多经过多少个点

具体请见完整代码的备注

完整代码:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <queue>
#define MAXN 2000010
using namespace std; int vis[MAXN], head[MAXN], hed[MAXN], jl[MAXN]={0};
int js=0, n, m, op=0, cnt=0;
int sta[MAXN], low[MAXN], dfn[MAXN], top=0;
int num[MAXN], sum[MAXN], g=0, oq=0; struct edge{//建两个图,一个用来存缩点前的图,一个用来存缩点后的图
int v, nxt;
}e[MAXN << 1], ed[MAXN << 1]; void addage(int u, int v){
e[++js].v = v;
e[js].nxt = head[u];
head[u] = js;
}//对缩点前的图进行加边 void add(int u, int v){
ed[++cnt].v = v;
ed[cnt].nxt = hed[u];
hed[u] = cnt;
}//对缩点后的图进行加边 void tarjan(int t){//用tarjan进行缩点(板子)
sta[++top] = t;
vis[t] = 1;
low[t] = dfn[t] = ++op;
for (int j = head[t]; j; j = e[j].nxt){
int v = e[j].v;
if (!dfn[v]){
tarjan(v);
low[t] = min (low[t], low[v]);
}
else if (vis[v])
low[t] = min (low[t], low[v]);
}
if (low[t] == dfn[t]){
int f = sta[top--];
vis[f] = 0;
num[f] = ++g;
sum[g]++;
while (f != t){
f = sta[top--];
vis[f] = 0;
num[f] = g;
sum[g]++;
}
}
} void spfa()//或者bfs(反正怎么叫是自己的事( ̄y▽ ̄)~*捂嘴偷笑)
{
int k;
queue<int> q;
memset(jl, 0, sizeof(jl));
memset(vis, 0, sizeof(vis));
vis[num[1]] = 0;
jl[num[1]] = 1;
q.push(num[1]);
while (!q.empty()){
k = q.front();
q.pop();
jl[k] = 0;
for (int i = hed[k]; i; i = ed[i].nxt)
if (vis[ed[i].v] < vis[k] + sum[ed[i].v])//注意这里,sum[]存的是一个强连通分量中有几个点
{
vis[ed[i].v] = vis[k] + sum[ed[i].v];//把sum[]当做点权来使用
if (!jl[ed[i].v])
{
q.push(ed[i].v);
jl[ed[i].v] = 1;
}
}
}
} int main(){
int x, y, v, ans=0, jss=0,mm;
scanf("%d %d", &n, &m);
for (int i = 1; i <= m; i++){
scanf("%d %d", &x, &y);
addage(x, y);
}
for (int i = 1; i <= n; i++)
if (!dfn[i]) tarjan(i);//tarjan缩点
for (int i = 1; i <= n; i++){
for (int j = head[i]; j; j = e[j].nxt){
v = e[j].v;
if (num[i] != num[v]){
add(num[i], num[v]);
add(num[v], num[i] + g);
add(num[i] + g, num[v] + g);
}//建分层图
}
}
for (int i = 1 + g; i <= g + g; i++) sum[i] = sum[i - g];//注意这里,我一开始样例死活过不去就是忘了加这一句
spfa();
printf("%d\n",vis[num[1] + g]);
return 0;
}

(代码不好看的话请原谅⁄(⁄ ⁄•⁄ω⁄•⁄ ⁄)⁄.)

【题解】洛谷P3119 Grass Cownoisseur G的更多相关文章

  1. 题解 洛谷 P2287 [USACO07NOV]Sunscreen G

    原题 传送门 有C个奶牛去晒太阳 (1 <=C <= 2500),每个奶牛各自能够忍受的阳光强度有一个最小值和一个最大值(minSPFi and maxSPFi),太大就晒伤了,太小奶牛没 ...

  2. P3119 [USACO15JAN]Grass Cownoisseur G

    P3119 [USACO15JAN]Grass Cownoisseur G tarjan缩点+分层图上跑 spfa最长路 约翰有 \(n\) 块草场,编号 \(1\) 到 \(n\),这些草场由若干条 ...

  3. 洛谷 P3119 [USACO15JAN]草鉴定Grass Cownoisseur 解题报告

    P3119 [USACO15JAN]草鉴定Grass Cownoisseur 题目描述 约翰有\(n\)块草场,编号1到\(n\),这些草场由若干条单行道相连.奶牛贝西是美味牧草的鉴赏家,她想到达尽可 ...

  4. 洛谷 P3119 [USACO15JAN]草鉴定Grass Cownoisseur (SCC缩点,SPFA最长路,枚举反边)

    P3119 [USACO15JAN]草鉴定Grass Cownoisseur 题目描述 In an effort to better manage the grazing patterns of hi ...

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

    P3119 [USACO15JAN]草鉴定Grass Cownoisseur 题目描述 In an effort to better manage the grazing patterns of hi ...

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

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

  7. BZOJ1563/洛谷P1912 诗人小G 【四边形不等式优化dp】

    题目链接 洛谷P1912[原题,需输出方案] BZOJ1563[无SPJ,只需输出结果] 题解 四边形不等式 什么是四边形不等式? 一个定义域在整数上的函数\(val(i,j)\),满足对\(\for ...

  8. 题解-洛谷P4229 某位歌姬的故事

    题面 洛谷P4229 某位歌姬的故事 \(T\) 组测试数据.有 \(n\) 个音节,每个音节 \(h_i\in[1,A]\),还有 \(m\) 个限制 \((l_i,r_i,g_i)\) 表示 \( ...

  9. 题解-洛谷P4724 【模板】三维凸包

    洛谷P4724 [模板]三维凸包 给出空间中 \(n\) 个点 \(p_i\),求凸包表面积. 数据范围:\(1\le n\le 2000\). 这篇题解因为是世界上最逊的人写的,所以也会有求凸包体积 ...

随机推荐

  1. 史上最全java里面的锁

    什么是锁 在计算机科学中,锁(lock)或互斥(mutex)是一种同步机制,用于在有许多执行线程的环境中强制对资源的访问限制.锁旨在强制实施互斥排他.并发控制策略. 锁通常需要硬件支持才能有效实施.这 ...

  2. sklearn中的SGDClassifier

    常用于大规模稀疏机器学习问题上 1.优点: 高效 简单 2.可以选择损失函数 loss="hinge": (soft-margin)线性SVM. loss="modifi ...

  3. ES6中class的使用+继承

    一.Class 介绍+基本语法(1).介绍通过class关键字,可以定义类.基本上,ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的 ...

  4. Docker 网络及命令

    Docker常用命令 docker version #查看版本 docker search centos #搜索可用docker镜像 docker images 查看当前docker所有镜像 dock ...

  5. Spring boot启动时报 java.sql.SQLException: java.lang.ClassCastException: java.math.BigInteger cannot be cast to java.lang.Long错误

    Spring boot启动时报 java.sql.SQLException: java.lang.ClassCastException: java.math.BigInteger cannot be ...

  6. Elasticsearch节点下线(退役)and unassigned shards

    一.节点退役当集群中个别节点出现故障预警等情况,需要进行退役工作,即让所有位于该退役节点上的分片的数据分配到其他节点上后,再将此节点关闭并从集群中移除. 1.ES提供了让某个节点上所有数据都移走的功能 ...

  7. Netty源码解析 -- 对象池Recycler实现原理

    由于在Java中创建一个实例的消耗不小,很多框架为了提高性能都使用对象池,Netty也不例外. 本文主要分析Netty对象池Recycler的实现原理. 源码分析基于Netty 4.1.52 缓存对象 ...

  8. DHCP.md

    DHCP 主配置文件   从 /usr/share/doc/dhcp 复制 dhcpd.conf.sample 到/etc/dhcp下                                  ...

  9. at定时任务

    1)at是只执行一次,执行完后任务删除.at的守护进程atd会以后台模式运行,检查作业队列来运行.2)默认 atd每60秒巡逻一次,有作业时候,检查作业时间,如果和当前时间一样,就执行任务3)在使用a ...

  10. java8新特性之stream流

    Stream 流是 Java 8 提供给开发者一套新的处理集合的API,他把我们将要处理的集合作为流,就像流水线一样,我们可以对其中的元素进行筛选,过滤,排序等中间操作,只不过这种操作更加简洁高效. ...