[Usaco2015 Jan]Grass Cownoisseur

题目大意:给一个有向图,然后选一条路径起点终点都为1的路径出来,有一次机会可以沿某条边逆方向走,问最多有多少个点可以被经过?(一个点在路径中无论出现多少正整数次对答案的贡献均为1)

数据范围:$1\le n, m\le 10^5$。


题解

先$tarjan$缩强连通分量,因为每一个$SCC$只要能到一个点就能到整个$SCC$。

接下来我们发现,我们操作的边的两个端点会满足如下性质:

这条有向边的起点可以到$1$号点所在$SCC$。

这条有向边的重点可以被$1$号点所在$SCC$到达。

故此,我们再缩完点之后,先对原图弄一遍拓扑序$DP$,求出$1$号点所在$SCC$到每个点的最长路。

再建反边重新跑拓扑序$DP$,求出每个点到$1$号点所在$SCC$的最长路。

暴力枚举边更新即可。

代码

#include <bits/stdc++.h>#define N 100010 using namespace std;int dep[N], low[N], st[N], top, cnt, blg[N], sz[N], f1[N], f2[N], d1[N], d2[N];int Number;bool ins[N];struct Node {int x, y;
}e[N];struct Edge {int head[N], to[N << 1], nxt[N << 1], tot;inline void add(int x, int y) {to[ ++ tot] = y;nxt[tot] = head[x];head[x] = tot;}
}G1,G2,G3;char *p1, *p2, buf[100000];#define nc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1 ++ )int rd() {int x = 0, f = 1;char c = nc();while (c < 48) {if (c == '-')f = -1;c = nc();}while (c > 47) {x = (((x << 2) + x) << 1) + (c ^ 48), c = nc();}return x * f;
}void tarjan(int p) {st[ ++ top] = p;ins[p] = true;low[p] = dep[p] = ++cnt;for (int i = G1.head[p]; i; i = G1.nxt[i]) {if (!dep[G1.to[i]])tarjan(G1.to[i]), low[p] = min(low[p], low[G1.to[i]]);else if (ins[G1.to[i]])low[p] = min(low[p], dep[G1.to[i]]);}if (dep[p] == low[p]) {int t;Number ++ ;do {t = st[top -- ];ins[t] = false;blg[t] = Number;sz[Number] ++ ;} while(t != p);}
}queue<int> q;void dp1() {while (!q.empty()) {q.pop();}memset(f1, 0xef, sizeof f1);for (int i = 1; i <= Number; i ++ ) {if (!d1[i]) {q.push(i);}}f1[blg[1]] = 0;while (!q.empty()) {int x = q.front();q.pop();f1[x] += sz[x];for (int i = G2.head[x]; i; i = G2.nxt[i]) {f1[G2.to[i]] = max(f1[G2.to[i]], f1[x]);d1[G2.to[i]] -- ;if (!d1[G2.to[i]]) {q.push(G2.to[i]);}}}
}void dp2() {while (!q.empty()) {q.pop();}for (int i = 1; i <= Number; i ++ ) {if (!d2[i]) {q.push(i);}}memset(f2, 0xef, sizeof f2);f2[blg[1]] = 0;while (!q.empty()) {int x = q.front();q.pop();f2[x] += sz[x];for (int i = G3.head[x]; i; i = G3.nxt[i]) {f2[G3.to[i]] = max(f2[G3.to[i]], f2[x]);d2[G3.to[i]] -- ;if (!d2[G3.to[i]]) {q.push(G3.to[i]);}}}
}int main() {int n = rd(), m = rd();if (!n)puts("1"), exit(0);for (int i = 1; i <= m; i ++ ) {e[i].x = rd(), e[i].y = rd();G1.add(e[i].x, e[i].y);}for (int i = 1; i <= n; i ++ ) {if (!dep[i]) {tarjan(i);}}// for (int i = 1; i <= n; i ++ ) {//     printf("%d ",blg[i]);// }// puts("");for (int i = 1; i <= m; i ++ ) {e[i].x = blg[e[i].x];e[i].y = blg[e[i].y];if (e[i].x != e[i].y) {// printf("%d %d\n", e[i].x, e[i].y);G2.add(e[i].x, e[i].y);d1[e[i].y] ++ ;G3.add(e[i].y, e[i].x);d2[e[i].x] ++ ;}}dp1();dp2();// for (int i = 1; i <= Number; i ++ ) {//     printf("%d %d\n", f1[i], f2[i]);// }int ans = sz[blg[1]];for (int i = 1; i <= m; i ++ ) {if (e[i].x != e[i].y) {ans = max(ans, f1[e[i].y] + f2[e[i].x] - sz[blg[1]]);}}cout << ans << endl ;return 0;
}

小结:比较好想的一道题,需要注意的是两边拓扑序$dp$需要清队列。

转载于:https://www.cnblogs.com/ShuraK/p/11255775.html

[bzoj3887][Usaco2015 Jan]Grass Cownoisseur_trajan_拓扑排序_拓扑序dp相关推荐

  1. python 拓扑排序_拓扑排序(topsort)算法详解

    在图论中,由某个集合上的偏序得到全序的策略就是拓补排序算法.拓扑排序常出现在涉及偏序关系的问题中,例如时序的先后.事物的依赖等.针对这些问题拓扑排序通常能有效地给出可行解. 为了便于理解,我们先来看一 ...

  2. 图综合练习--拓扑排序_拓扑排序

    一个场景 在大学里,每当到了期末的时候,你一定会头疼于选课给你带来的困扰.其中一项就是先修课的问题,每次你高高兴兴地选了自己心仪的选修课时,却发现自己不满足先修课的要求,只好默默地退掉.到底怎样安排我 ...

  3. AOV网络、拓扑排序、拓扑序列

    AOV网络 AOV网是有向图的一类应用,在AOV网中,用顶点表示某个有一定规模的"工程"里的不同活动,用图中的边表示各项活动之间的先后顺序关系.一种常见的AOV网实例是大学课程的先 ...

  4. java_排序_正序

    java_排序_正序 List List<Integer> integerList = new ArrayList<>();integerList.add(6);integer ...

  5. Bailian4084 拓扑排序【拓扑排序】

    4084:拓扑排序 总时间限制: 1000ms 内存限制: 65536kB 描述 给出一个图的结构,输出其拓扑排序序列,要求在同等条件下,编号小的顶点在前. 输入 若干行整数,第一行有2个数,分别为顶 ...

  6. 图论入门(一),拓扑排序生成拓扑序列与Dijkstra求最短路

    基本知识 Dijkstra基本思想 拓扑排序思维视频讲解 848:有向图的拓扑排序 题目链接 题解: #include<bits/stdc++.h> using namespace std ...

  7. python 拓扑排序_Python 拓扑排序

    Python 拓扑排序 对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G) ...

  8. 判断图有无环_浅谈什么是图拓扑排序

    1 引言   在工程实践中,一个工程项目往往由若干个子项目组成.这些子项目间往往有两种关系:   (1) 先后关系,即必须在某个项完成后才能开始实施另一个子项目.   (2) 子项目间无关系,即两个子 ...

  9. 拓扑排序之java实现_有向图和拓扑排序Java实现

    package practice; import java.util.ArrayDeque; import java.util.Iterator; import java.util.Stack; pu ...

  10. 【学术篇】2.28测试T2 线段 拓扑排序

    题目: 思路: 看到这种找前后的题目... 第一反应就是拓扑排序_(:з」∠)_ 每条线段都有左右两个端点咯, 然后就乱搞吧.. 我们用\(i\)和\(i'\)分别表示第\(i\)条线段的左右端点.. ...

最新文章

  1. python qthread 线程退出_线程:概念和实现
  2. Subversion For Windows的安装与使用
  3. mysql权限配置文件_MySQL权限管理、配置文件(三)
  4. Nginx反向代理之proxy_pass指令
  5. 《深入理解JVM.2nd》笔记(一):走进Java
  6. 信息学奥赛一本通(1263:【例9.7】友好城市)
  7. 表的连接方式:NESTED LOOP、HASH JOIN、SORT MERGE JOIN【转】
  8. 华为P50系列即将发布:麒麟9000E/9000处理器有戏?
  9. I00030 Grades conversion
  10. mysql 1093_mysql ERROR 1093 (HY000)
  11. 【AE教程】AI文件导入AE方法
  12. 基于企业战略的业务流程重组与外包(2) (转载)
  13. icewm+rox-filer美化过程(转)
  14. 国产操作系统能不能完全替代windows,普及大众?
  15. 梯度,也即该物理参数的变化率,导数
  16. 丑数求解以及丑数的优化
  17. 解决 yarn install报错node-sass: Command failed/使用nvm use出现status 145:the directory is not empty
  18. 大前端养成之路:学一点MongoDB(一)
  19. SQL系列五——子查询(SELECT)和组合查询(UNION)
  20. 苹果手机充电口接触不良怎么办_充电器接触不良怎么办 高手来教你几招-装修攻略...

热门文章

  1. 网站流量分析数据指标
  2. css 实现导航菜单
  3. 1114 Family Property (25 point(s))
  4. SPSS中的数据分析—信度效度检验【1】
  5. 二倍图三倍图什么意思_ios切图(一倍图+二倍图+三倍图)
  6. 北京智能机器人为游客指路;日本研发出可识别背影的人工智能
  7. java水彩画效果滤镜,教你巧用PS滤镜实现水彩画效果
  8. 【转】地址线和数据线的计算
  9. 三角形~~行列式~~皮克公式~~gcd
  10. 【微积分3一元函数积分学】第三章第三节 反常积分