当前位置:网站首页>最大半连通子图(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;
}
边栏推荐
猜你喜欢

「百度一面」怒喷面试官!不就是树遍历时增加一个行号?

How to build dashboard and knowledge base in double chain note taking software? Take the embedded widget library notionpet as an example

军品研制过程所需文件-进阶版

分类任务中的类别不平衡问题

从预测到决策,九章云极DataCanvas推出YLearn因果学习开源项目

腾讯云服务器利用镜像部署WordPress个人网站!

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

Design of the multi live architecture in different places of the king glory mall

Aike AI frontier promotion (7.17)

LeetCode 2325. Decrypt message (map)
随机推荐
SAP AppGyver 的 Universal Theme System 使用介绍
多元线性回归详解
AutoJs学习-多功能宝箱-下
企业远程办公如何更高效?
Pytorch.nn实现多层感知机
Establishment of redis cluster, one master, two slave and three Sentinels
Openfoam heat flow boundary condition
Autojs learning - multi function treasure chest - medium
从“被动”到“主动”,ZETA技术助力“RFID2.0”升级该如何实现?
ROS 重名
Virtual CPU and memory in yarn (CDH)
[design process] Net ORM FreeSQL wheredynamicfilter dynamic table query function
SAP ABAP CDS view 视图的 Replacement 技术介绍
机器学习模型的评估方法
LeetCode 2315. 统计星号(字符串)
树的基本操作
常见集合特性
"Baidu side" angrily sprayed the interviewer! Isn't it that the tree time increases by a line number?
6G中的卫星通信高效天基计算技术
String类型函数传递问题