luogu3119 草鉴定
题目大意
给出一个有向图,问将图中的哪一个边翻转,会使节点1所在的强连通分量内的节点数最多。输出这个节点数。
题解
让我们看看暴力怎么做,即枚举每一条边,将其翻转,然后求节点1所在强连通分量节点数,然后取最大值。我们看到如果一条边连接的两个节点位于同一个强连通分量中,那么将这条边翻转只可能拆解已有的强连通分量,并使结果变差。因此,我们对强连通分量进行缩点(点权为强连通分量的节点个数)构成一个新图。
所以我们要在新图中暴力吗?不可以。怎样能达到“反向边只走一次”这个限制条件呢呢?分层图就能解决这个问题。原图复制一份得到上层图。把反向边起点连在原图上,终点连在上层图上,我们要求一个原图上的1节点走向上层图1节点的点权最长路径,它只会从原图走向上层图,不会从上层图走向下层图,这样就满足限制条件了。因为是点权,故我们拆点为边(以后简称“拆点边”)。
另外,这么做满足除了1节点外,在原图1节点到上层图1节点的路径上,不存在原图和上层图对应的拆点边计算两次的情况,因为如果计算了两次,那么在下层图上也会存在一条和整条路径在上层图上的部分相同的一条路径返回1节点,这样的路径构成了一个环,不满足强连通分量的定义。
另外注意,当有拆点、分层图时,开的空间要写到纸上。总共100000个点,分层图*2,拆点*2,故总共*4。原先我忘了拆点还要*2。。。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <stack>
#include <cassert>
using namespace std; const int MAX_NODE = 100010, MAX_EDGE = 100010, MINF = 0xcfcfcfcf; struct TarjanGraph
{
public:
struct Block
{
int Size;
vector<int> Next;
}_blocks[MAX_NODE];
int BlockCnt; private:
struct Node
{
vector<Node*> Next;
int DfsN, Low, BlockIn;
bool InStack;
}_nodes[MAX_NODE];
int DfsCnt, TotNode;
stack<Node*> St; void Destack(Node *cur)
{
BlockCnt++;
Node *temp;
do {
temp = St.top();
St.pop();
temp->BlockIn = BlockCnt;
temp->InStack = false;
_blocks[BlockCnt].Size++;
} while (temp != cur);
} void Dfs(Node *cur)
{
cur->Low = cur->DfsN = ++DfsCnt;
cur->InStack = true;
St.push(cur);
for (unsigned int i = 0; i < cur->Next.size(); i++)
{
if (!cur->Next[i]->DfsN)
{
Dfs(cur->Next[i]);
cur->Low = min(cur->Low, cur->Next[i]->Low);
}
else if (cur->Next[i]->InStack)
cur->Low = min(cur->Low, cur->Next[i]->DfsN);
}
if (cur->Low == cur->DfsN)
Destack(cur);
} public:
void Init(int totNode)
{
TotNode = totNode;
} void AddEdge(int u, int v)
{
_nodes[u].Next.push_back(_nodes + v);
} void GetBlock()
{
for (int i = 1; i <= TotNode; i++)
if (!_nodes[i].DfsN)
Dfs(_nodes + i); for (int i = 1; i <= TotNode; i++)
for (unsigned int j = 0; j < _nodes[i].Next.size(); j++)
if (_nodes[i].BlockIn != _nodes[i].Next[j]->BlockIn)
_blocks[_nodes[i].BlockIn].Next.push_back(_nodes[i].Next[j]->BlockIn);
} int GetBlockIn(int v)
{
return _nodes[v].BlockIn;
}
}g; struct TopGraph
{
private:
struct Node;
struct Edge; struct Node
{
Edge *Head;
int Dist;
int DfsN;//0:未访问 1:在系统栈内 2:处理完毕
}_nodes[MAX_NODE * 4];
int TotNode;
stack<Node*> St; struct Edge
{
Node *To;
Edge *Next;
int Weight;
}_edges[MAX_EDGE * 3 + MAX_NODE * 2];
int _eCount; void Dfs(Node *cur)
{
assert(cur->DfsN != 1);
if (cur->DfsN == 2)
return;
cur->DfsN = 1;
for (Edge *e = cur->Head; e; e = e->Next)
Dfs(e->To);
cur->DfsN = 2;
St.push(cur);
} public:
void Init(int totNode)
{
TotNode = totNode;
} void AddEdge(int u, int v, int w)
{
Node *from = _nodes + u, *to = _nodes + v;
Edge *e = _edges + ++_eCount;
e->To = to;
e->Weight = w;
e->Next = from->Head;
from->Head = e;
} int LongestPath(int s, int t)
{
Dfs(_nodes + s);
for (int i = 1; i <= TotNode; i++)
_nodes[i].Dist = MINF;
_nodes[s].Dist = 0;
while (!St.empty())
{
Node *cur = St.top();
St.pop();
for (Edge *e = cur->Head; e; e = e->Next)
e->To->Dist = max(e->To->Dist, cur->Dist + e->Weight);
}
return _nodes[t].Dist;
}
}t; int main()
{
int totNode, totEdge;
scanf("%d%d", &totNode, &totEdge);
g.Init(totNode);
for (int i = 1; i <= totEdge; i++)
{
int u, v;
scanf("%d%d", &u, &v);
g.AddEdge(u, v);
}
g.GetBlock();
t.Init(g.BlockCnt * 2);
for (int i = 1; i <= g.BlockCnt; i++)
{
t.AddEdge(i * 2 - 1, i * 2, g._blocks[i].Size);
t.AddEdge((i + totNode) * 2 - 1, (i + totNode) * 2, g._blocks[i].Size);
for (unsigned int j = 0; j < g._blocks[i].Next.size(); j++)
{
int v = g._blocks[i].Next[j];
t.AddEdge(i * 2, v * 2 - 1, 0);
t.AddEdge((i + totNode) * 2, (v + totNode) * 2 - 1, 0);
t.AddEdge(v * 2, (i + totNode) * 2 - 1, 0);
}
}
printf("%d\n", t.LongestPath(g.GetBlockIn(1) * 2 - 1, (g.GetBlockIn(1) + totNode) * 2 - 1));
return 0;
}
luogu3119 草鉴定的更多相关文章
- Luogu3119 草鉴定-Tarjan+Topsort
Solution 简单的$Tarjan$题. 有大佬现成博客 就不写了 → 传送门 Code #include<cstdio> #include<cstring> #inclu ...
- 洛谷 P3119 [USACO15JAN]草鉴定Grass Cownoisseur 解题报告
P3119 [USACO15JAN]草鉴定Grass Cownoisseur 题目描述 约翰有\(n\)块草场,编号1到\(n\),这些草场由若干条单行道相连.奶牛贝西是美味牧草的鉴赏家,她想到达尽可 ...
- 【洛谷P3119】[USACO15JAN]草鉴定Grass Cownoisseur
草鉴定Grass Cownoisseur 题目链接 约翰有n块草场,编号1到n,这些草场由若干条单行道相连.奶牛贝西是美味牧草的鉴赏家,她想到达尽可能多的草场去品尝牧草. 贝西总是从1号草场出发,最后 ...
- 洛谷——P3119 [USACO15JAN]草鉴定Grass Cownoisseur
P3119 [USACO15JAN]草鉴定Grass Cownoisseur 题目描述 In an effort to better manage the grazing patterns of hi ...
- [USACO15JAN]草鉴定Grass Cownoisseur(分层图+tarjan)
[USACO15JAN]草鉴定Grass Cownoisseur 题目描述 In an effort to better manage the grazing patterns of his cows ...
- 洛谷P3119草鉴定
题目 草鉴定,tarjan可以用来缩点,优化spfa的时间, 缩点之后就是一个\(DAG\)了,因此完全可以用来跑spfa上的最长路,然后枚举每条边,查看是否这条边的两个节点分别可以到达起点所在的强连 ...
- 洛谷 P3119 [USACO15JAN]草鉴定Grass Cownoisseur (SCC缩点,SPFA最长路,枚举反边)
P3119 [USACO15JAN]草鉴定Grass Cownoisseur 题目描述 In an effort to better manage the grazing patterns of hi ...
- luogu3119/bzoj3887 草鉴定 (tarjan缩点+spfa)
首先缩一波点,就变成了一个DAG,边权是出点的大小 那我们走到某个点的时候可能会有两种状态:已经走过反边或者没走过 于是就把一个点拆成两层(x和x+N),第二层的点表示我已经走过反边了,每层中的边和原 ...
- P3119 [USACO15JAN]草鉴定Grass Cownoisseur
题目描述 In an effort to better manage the grazing patterns of his cows, Farmer John has installed one-w ...
随机推荐
- iOS keychain入门
学了很久的iOS,一直都是明文保存用户名和密码在本地,手机一般都是自己用的,而且非越狱手机东西也不怎么能拿到数据,所以也就没在乎那么多,当然,这是不科学的.悄悄的说,这块一直不是我写的~~~ 用户隐私 ...
- Python爬取贴吧中的图片
#看到贴吧大佬在发图,准备盗一下 #只是爬取一个帖子中的图片 1.先新建一个scrapy项目 scrapy startproject TuBaEx 2.新建一个爬虫 scrapy genspider ...
- 挂载硬盘,提示 mount: unknown filesystem type 'LVM2_member'的解决方案
问题现象:由于重装linux,并且加了固态硬盘,直接将系统装在固态硬盘中.启动服务器的时候, 便看不到原来机械硬盘的挂载目录了,不知如何访问机械硬盘了.直接用命令 mount /dev/sda3 /s ...
- Centos 编译安装Haproxy
一.环境介绍 1.Centos6 2. haproxy-1.4.25.tar.gz 二.安装 $ curl -O http://haproxy.1wt.eu/download/1.4/src/hapr ...
- 爬虫解析库BeautifulSoup的一些笔记
BeautifulSoup类使用 基本元素 说明 Tag 标签,最基本的信息组织单元,分别是<>和</>标明开头和结尾 Name 标签的名字,<p></p ...
- CAD保存DWG文件,设置保存的文件版本号和密码
主要用到函数说明: MxDrawXCustomFunction::Mx_SaveDwgEx 保存DWG文件,可以设置保存的文件版本号和密码,详细说明如下: 参数 说明 IN CString sFile ...
- SpringMVC知识点总结一(非注解方式的处理器与映射器配置方法)
一.SpringMVC处理请求原理图(参见以前博客) 1. 用户发送请求至前端控制器DispatcherServlet 2. DispatcherServlet收到请求调用HandlerMappi ...
- Spring处理自动装配的歧义性
1.标识首选的bean 2.使用限定符@Qualifier 首先在bean的声明上添加@Qualifier 注解: @Component @Qualifier("cdtest") ...
- C语言中的DEBUG
#cat aa.c #include <stdio.h> #include <stdarg.h> #include <stdlib.h> #include < ...
- enote笔记语言(2)(ver0.2)
why not(whyn't) 为什么不(与“why”相对应,是它的反面) how对策 how设计 key-memo ...