这时yxc上课时讲解的截图。

一般用到tarjan算法的题目步骤都非常相似:

  1. tarjan算法
  2. 缩点,建图(这里要判重)
  3. 按照拓扑序递推(这里缩点以后逆向就已经是拓扑序了)/ 循环遍历新图求解答案。

导出子图:点是原图的子集,边一定包含与子图中所有点有关的边。
半联通子图:所有的两个点,我要么可以直接一条路过去,要么你可以直接过来。
显然,对于任意一个强连通分量S∈GS\in GS∈G,它一定一个半连通子图,于是我们可以考虑先缩点。缩点之后,原图变成了一个有向无环图,显然,对于任意一条DAG中的一条单向到达的链,它都是一个半连通子图。

所以答案K就是DAG中最大链的顶点个数,答案C就是DAG中不同的最大链有多少种。
由于整个DAG按顺序已经是一个拓扑序了,所以我们可以直接递推DP线性O(n)O(n)O(n)求答案。 设size(u)表示顶点u代表的强连通分量
S中的顶点个数,f(u)表示从顶点u开始延伸的最大链的顶点个数,g(u)表示从顶点u开始延伸的不同的最大链有多少个,则有:
f(u)=size(u)+max(f(v))(u→v)f(u)=size(u)+max(f(v))\ \ \ \ (u\to v)f(u)=size(u)+max(f(v))    (u→v)

g(u)=∑g(v)(u→v,size(u)+f(v)=f(u))g(u)=∑g(v)(u→v,size(u)+f(v)=f(u))g(u)=∑g(v)(u→v,size(u)+f(v)=f(u))每次从一个没有被访问过的顶点开始做深度优先搜索,回溯时计算每个顶点的f,g值。K,C也可以按照相同的方式进行更新。

本题需要判重去重,因为第二问是总的方案数,如果边是一摸一样的那么方案应该是同一种,所以如果不判重就会影响最后的答案。我们直接用一个set判重,顺便用到一个巧妙的hash,因为我们一共就只有100000个点,所以我们直接把所有的点都映射到100000+v即可,不会产生冲突。
需要注意的是建完的图是逆拓扑序,按照拓扑序递推DP,所以必须倒着来循环DP。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<unordered_set>using namespace std;const int N = 100007, M = 2000007, INF = 0x3f3f3f3f;typedef long long ll;
int mod;
int n, m;
int dfn[N], low[N], num;
int ver[M], edge[M], head[N], nex[M], tot;
int h[N];int Size[N], scc_cnt, scc_id[N];
int stk[N], top, ins[N];int f[N], g[N];//顶点个数和方案数void add(int h[],int x,int y){ver[tot] = y;nex[tot] = h[x];h[x] = tot ++ ;
}void tarjan(int x){dfn[x] = low[x] = ++ num;stk[ ++ top] = x;ins[x] = true;for(int i = head[x];~i;i = nex[i]){int y = ver[i];if(!dfn[y]){tarjan(y);low[x] = min(low[x],low[y]);}else if(ins[y]){low[x] = min(low[x], dfn[y]);}}if(dfn[x] == low[x]){int y;++ scc_cnt;do{y = stk[top -- ];ins[y] = false;scc_id[y] = scc_cnt;Size[scc_cnt] ++ ;}while(x != y);}
}int main()
{memset(head,-1,sizeof head);memset(h,-1,sizeof h);scanf("%d%d%d",&n,&m,&mod);while(m -- ){int x,y;scanf("%d%d",&x,&y);add(head,x,y);}for(int i = 1;i <= n;++i)if(!dfn[i])tarjan(i);unordered_set<ll>st;//(u,v) -> u * 1000000 + v;//因为一共只有100000个点for(int i = 1;i <= n;++i){for(int j = head[i];~j;j = nex[j]){int k = ver[j];int a = scc_id[i], b = scc_id[k];ll hash = a * 100000ll + b;//建新图并判重if(a != b && !st.count(hash)){add(h,a,b);st.insert(hash);}}}for(int i = scc_cnt;i >= 1;-- i){//建完的图是逆拓扑序,按照拓扑序递推,所以必须倒着来if(!f[i]){f[i] = Size[i];g[i] = 1;}for(int j = h[i];~j;j = nex[j]){int k = ver[j];if(f[k] < f[i] + Size[k]){f[k] = f[i] + Size[k];g[k] = g[i];}else if(f[k] == f[i] + Size[k]){g[k] = (g[k] + g[i]) % mod;}}}ll maxx = 0,sum = 0;for(int i = 1;i <= n;++i){if(f[i] > maxx){maxx = f[i];sum = g[i];}else if(f[i] == maxx){sum = (sum + g[i] ) % mod;}}printf("%lld\n%lld\n",maxx, sum);return 0;
}

解题报告:luogu P2272 [ZJOI2007]最大半连通子图(tarjan缩点、递推DP、hash、set判重)相关推荐

  1. BZOJ 1093 [ZJOI2007]最大半连通子图

    1093: [ZJOI2007]最大半连通子图 Description 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意 ...

  2. P2272-[ZJOI2007]最大半连通子图【tarjan,缩点】

    正题 题目链接:https://www.luogu.com.cn/problem/P2272 题目大意 半连通图定义为任意两个点(u,v)(u,v)(u,v)满足uuu可以到vvv或vvv可以到uuu ...

  3. tyvj——P3524 最大半连通子图

    P3524 最大半连通子图 时间: 3000ms / 空间: 165536KiB / Java类名: Main 描述 输入格式 第一行包含两个整数N,M,X.N,M分别表示图G的点数与边数,X的意义如 ...

  4. BZOJ 1093 ZJOI 2007 最大半连通子图 强联通分量+拓扑图DP

    今天是放假的第一天(不说什么废话了) 什么是半连通子图?就是此图中包含的所有点两两点之间至少有一条单向路径. 题目问了两个问题 1.最大半连通子图的大小 2.最大半连通子图的个数 好了,这个问题看上去 ...

  5. luogu P4240 毒瘤之神的考验(莫比乌斯反演+递推前缀和+数论分块)

    problem 洛谷链接 solution ∑i=1n∑j=1mφ(ij)=∑i=1n∑j=1mφ(i)φ(j)gcd⁡(i,j)φ(gcd⁡(i,j))\sum_{i=1}^n\sum_{j=1}^ ...

  6. 有向图的强连通分量——最大半联通子图

    最大半联通子图 一个有向图 G=(V,E)G=(V,E)G=(V,E) 称为半连通的 (Semi-Connected),如果满足:∀u,v∈V,满足u→v或v→u∀u,v∈V,满足 u→v 或 v→u ...

  7. 解题报告(十八)数论题目泛做(Codeforces 难度:2000 ~ 3000 + )

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量的题解和代码,题目难度不一 ...

  8. 解题报告(八) prufer 序列与 Cayley 公式(ACM / OI)超高质量题解

    繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量题解和代码,题目难度不一定按照题号排序,我会在每道题后面加上题目难度指数(1∼51 \sim 51∼5),以模板题难度 11 ...

  9. 【解题报告系列】超高质量题单 + 题解(ACM / OI)超高质量题解

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我新写的超高质量的题解和代码,题目难度不 ...

最新文章

  1. Mozilla开源了VR框架A-Frame
  2. 【NOIP模拟】T1 发电机(递推逆元+期望)
  3. 关于省客服集中全业务系统IT项目管理的几点分析!
  4. WebView.onDraw (Android 4.1)
  5. ApplicationInsights的探测器尝鲜
  6. 模板:拉格朗日插值(多项式)
  7. java编程中的持有对方引用是什么意思?有什么作用?
  8. 2022年中国物联网行业研究报告
  9. 100路监控需要使用核心交换机吗?
  10. delphi 控件安装
  11. ssh隧道(通过跳板机)连接mysql
  12. Wireshark 抓包小例子
  13. php mysql 用户修改_PHP+MYSQL实现用户的增删改查,mysql增删_PHP教程
  14. php防止网站被镜像,网站防止被其他站iframe框架引用镜像的方法
  15. 秋天网站快速部署系统 一.入门使用
  16. 云计算机可以玩游戏吗,免费云桌面系统能跟云电脑一样玩游戏吗?
  17. Apollo星火计划学习笔记——第八讲Apollo控制模块解析与实践1
  18. PHP windoews调用OpenOffice实现word/ppt转PDF-附带demo
  19. 顶会最佳论文奖得主:初入科研领域,如何正确做科研?
  20. 贪心算法的最优解条件

热门文章

  1. 清晰易懂的Numpy进阶教程
  2. 12个深度学习面试问题
  3. Pytorch中的5个非常有用的张量操作
  4. Batch Normalization应该放在ReLU非线性激活层的前面还是后面?
  5. iOS 的组件化开发
  6. IDEA 配置maven
  7. HDFS-Shell
  8. java.lang.RuntimeException: Expected one of local, maven-local, maven-central, scala-tools-releases,
  9. WSL windows子系统开启ssh-server服务
  10. windows10删除更新的程序