题目大意

  给出一个有向图,问将图中的哪一个边翻转,会使节点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 草鉴定的更多相关文章

  1. Luogu3119 草鉴定-Tarjan+Topsort

    Solution 简单的$Tarjan$题. 有大佬现成博客 就不写了 → 传送门 Code #include<cstdio> #include<cstring> #inclu ...

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

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

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

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

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

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

  5. [USACO15JAN]草鉴定Grass Cownoisseur(分层图+tarjan)

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

  6. 洛谷P3119草鉴定

    题目 草鉴定,tarjan可以用来缩点,优化spfa的时间, 缩点之后就是一个\(DAG\)了,因此完全可以用来跑spfa上的最长路,然后枚举每条边,查看是否这条边的两个节点分别可以到达起点所在的强连 ...

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

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

  8. luogu3119/bzoj3887 草鉴定 (tarjan缩点+spfa)

    首先缩一波点,就变成了一个DAG,边权是出点的大小 那我们走到某个点的时候可能会有两种状态:已经走过反边或者没走过 于是就把一个点拆成两层(x和x+N),第二层的点表示我已经走过反边了,每层中的边和原 ...

  9. P3119 [USACO15JAN]草鉴定Grass Cownoisseur

    题目描述 In an effort to better manage the grazing patterns of his cows, Farmer John has installed one-w ...

随机推荐

  1. Windows下apache+tomcat负载均衡

    Windows下apache+tomcat负载均衡 网上已经有很多的资料,但是很多都比较零碎,需要整合一起才能搭建出理想的负载均衡,正好前段时间搭建了windows与linux下的负载均衡,在此记录, ...

  2. SSH Secure Shell Client连接centos6.5时中文字乱码处理

    在学习Linux的过程中,最先碰到的是通过SSH终端连接时发现有乱码出现,使用这篇文章先从这里说起. 在 ssh , telnet 终端中文显示乱码解决办法#vim /etc/sysconfig/i1 ...

  3. fcc 响应式框架Bootstrap 练习3

    class="container-fluid"控制宽度100% <div class="container-fluid"> <h3 class ...

  4. Java Web框架前景浅析

    基于三(多)层架构模式,典型WEB系统的总体架构如下图所示: 在上述分层架构中,整个应用被划分为两大部分: 客户端:基于浏览器提供信息展现.用户交互等功能.所采用的技术主要有:HTML/HTML5.J ...

  5. jsp 中包含 一个路径为变量的文件

    <head> <base href="<%=basePath%>"> <% String fileroot="MyJsp.jsp ...

  6. CSS——属性选择器

    属性选择器:通过对标签中属性的选择,控制标签. <!DOCTYPE html> <html> <head> <style> div[class*=&qu ...

  7. nested exception is java.io.FileNotFoundException: class path resource [jdbc.properties] cannot be opened because it does not exist

    Could not load properties; nested exception is java.io.FileNotFoundException: class path resource [j ...

  8. 【译】x86程序员手册03 - 2.1内存组织和分段

    2.1 Memory Organization and Segmentation 内存组织和分段 The physical memory of an 80386 system is organized ...

  9. 【译】x86程序员手册02 - 基本的程序模式

    Chapter 2 -- Basic Programming Model: 基本的程序模式 Introduces the models of memory organization. Defines ...

  10. Dynamics 365 CRM Connected Field Service 自动发送command

    上期降到了怎样部署connected field service(CFS) 我们假设现在IoT 设备是温度监控器, 当温度触发我们之前预设的温度值, IoT会通过IoT Hub 发送IoT Alert ...