当前位置:网站首页>最大半连通子图(tarjan缩点+拓扑排序+dp最长链)
最大半连通子图(tarjan缩点+拓扑排序+dp最长链)
2022-07-17 13:23:00 【Snow_raw】
最大半连通子图(tarjan缩点+拓扑排序+dp最长链)
洛谷P2272
基本知识点:
1 : 1: 1:联通分量: u < = > v u<=>v u<=>v半联通分量: u = > v u=>v u=>v o r or or v = > u v=>u v=>u
2 : 2: 2:子图:节点集和边集分别是某一图的节点集的子集和边集的子集的图
3 : 3: 3:连通分量必定是半连通分量,反之不一定
思路:
1 : 1: 1: 题目第 1 1 1 个要求是求最大半连通子图的节点数 即节点数最多的半连通子图 。显然由于连通分量一定是半连通分量,所以我们可以通过 t a r j a n tarjan tarjan 将连通分量缩成一个点,从而将图转化为 有向无环图 即( DAG )。
2 : 2: 2: 通过 t a r j a n tarjan tarjan 缩点形成的所有 SCC ,自编号最大的 SCC 到编号最小的 SCC 遍历的过程即一个 DAG 过程,因为 t a r j a n tarjan tarjan 是一个 d f s dfs dfs 序的过程。
3 : 3: 3: 各连通分量( 缩点后即各个顶点 )之间可能存在多条边,所以我们需要另建图,使得两顶点之间只有一条边有向边关联,最终方可统计正确的 最大半连通子图的数目 ,否则会重复更新,因为两点之间存在多条边。
4 : 4: 4: 最后从最大编号的 SCC 开始跑拓扑并且 dp 实时更新即可。
5 : 5: 5: 最后统计 最多数量的半连通子图中顶点数,如果存在多个最大半连通子图累加取模即可 。
代码:
/* * @author: Snow * @LastEditTime: 2022-07-14 23:01:43 * @Description: Algorithm Contest */
#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
#define int long long
#pragma GCC optimize(3)
typedef pair<int,int>PII;
#define emplace_back() pb;
const int N = 1e5+10,M = 2e6+10;
int n,m,mod;
int h[N],e[M],ne[M],idx,h1[N];
int stk[N],top,scc_cnt,dfn[N],low[N],timestamp,id[N],scc_size[N];
bool in_stk[N];
int dp[N];
int cnt[N];
void add(int h[],int a,int b){
e[idx]=b;
ne[idx]=h[a];
h[a]=idx++;
}
void tarjan(int u){
in_stk[u]=true;
stk[++top]=u;
dfn[u]=low[u]=++timestamp;
for(int i=h[u];i!=-1;i=ne[i]){
int j=e[i];
if(!dfn[j]){
tarjan(j);
low[u]=min(low[u],low[j]);
}
else if(in_stk[j]){
low[u]=min(low[u],dfn[j]);
}
}
if(low[u]==dfn[u]){
int y;
++scc_cnt;
do{
y=stk[top--];
in_stk[y]=false;
id[y]=scc_cnt;
scc_size[scc_cnt]++;
}while(y!=u);
}
}
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin>>n>>m>>mod;
memset(h,-1,sizeof h);
memset(h1,-1,sizeof h1);
for(int i=1;i<=m;i++){
int a,b;
cin>>a>>b;
add(h,a,b);
}
for(int i=1;i<=n;i++){
if(!dfn[i])tarjan(i);
}
unordered_map<int,int>mp;
for(int i=1;i<=n;i++){
for(int j=h[i];j!=-1;j=ne[j]){
int k=e[j];
int a,b;
a=id[i],b=id[k];
int hash=a*1000000+b;
if(a!=b){
if(!mp[hash]){
mp[hash]=1;
add(h1,a,b);
}
}
}
}
for(int i=scc_cnt;i>=1;i--){
if(!dp[i]){
dp[i]=scc_size[i];
cnt[i]=1;
}
for(int j=h1[i];j!=-1;j=ne[j]){
int k=e[j];
if(dp[k]<dp[i]+scc_size[k]){
dp[k]=dp[i]+scc_size[k];
cnt[k]=cnt[i];
}
else if(dp[k]==dp[i]+scc_size[k]){
cnt[k]=(cnt[k]+cnt[i])%mod;
}
}
}
int ma=0,sum=0;
for(int i=1;i<=scc_cnt;i++){
if(dp[i]>ma){
ma=dp[i];
sum=cnt[i];
}
else if(dp[i]==ma){
sum=(sum+cnt[i])%mod;
}
}
cout<<ma<<endl<<sum<<endl;
return 0;
}
边栏推荐
- 自动化之图形界面库pyautogui
- Connected graph (union search set)
- Google Earth Engine——Hansen Global Forest Change v1.8 (2000-2020) 森林覆盖度和森林损失量数据集
- 机器学习模型的评估方法
- 博弈论(depu)与投资(40/100)
- Leetcode ugly number problem solution
- 树链剖分思想讲解 + AcWing 2568. 树链剖分(dfs序 + 爬山法 + 线段树)
- [makefile] some notes on the use of makefile
- [Niuke swipe questions] / *c language realizes left-hand rotation of strings*/
- VScode+Unity3D的配置
猜你喜欢

ue4对动画蓝图的理解

win10开始键点击无响应

unity3d如何利用asset store下载一些有用的资源包

Bidirectional NAT Technology

"Baidu side" angrily sprayed the interviewer! Isn't it that the tree time increases by a line number?

Data Lake solutions of various manufacturers

How to use SVG to make text effects arranged along any path

如何在双链笔记软件中建立仪表盘和知识库?以嵌入式小组件库 NotionPet 为例

Common collection properties

Domestic flagship mobile phones have a serious price foam, and second-hand phones are more cost-effective than new ones, or buy iPhones
随机推荐
How to build dashboard and knowledge base in double chain note taking software? Take the embedded widget library notionpet as an example
英伟达用AI设计GPU:最新H100已经用上,比传统EDA减少25%芯片面积
树链剖分思想讲解 + AcWing 2568. 树链剖分(dfs序 + 爬山法 + 线段树)
企业远程办公如何更高效?
VScode+Unity3D的配置
antd表单设置数组字段
内核态和用户态
[acwing] game 60 c-acwing 4496 eat fruit
C serialport configuration and attribute understanding
分类任务中的类别不平衡问题
华为机试:连续出牌数量
博弈论(depu)与投资(40/100)
Avi 部署使用指南(2):Avi 架构概述
【在vivado中调ila IP核】
(二)使用MySQL
过拟合与欠拟合
Vérification logique complexe personnalisée lors de l'ajout et de la modification - 2022 nouvel élément
AutoJs学习-多功能宝箱-下
[Acwing]第 60 场周赛 B- 4495. 数组操作
c语言指针的有关总结