LG2272/BZOJ1093 「ZJOI2007」最大半连通子图 Tarjan缩点+DAG求最长链
问题描述
题解
观察半联通的定义,发现图中的一些结点,构成的链一定是一个半联通子图。
此时存在的环可能会干扰求解,于是\(\mathrm{Tarjan}\)缩点。
于是求最长链,过程中计数即可。
\(\mathrm{Code}\)
#include<bits/stdc++.h>
using namespace std;
template <typename Tp>
void read(Tp &x){
x=0;char ch=1;int fh;
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-'){
fh=-1;ch=getchar();
}
else fh=1;
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+ch-'0';
ch=getchar();
}
x*=fh;
}
const int maxn=100000+7;
const int maxm=1000000+7;
int n,m,mod;
int Head_old[maxn],Next_old[maxm],to_old[maxm],tot_old,u_old[maxm];
int Head_new[maxn],Next_new[maxm],to_new[maxm],tot_new,u_new[maxm];
int size[maxn];
void add_old(int x,int y){
to_old[++tot_old]=y,Next_old[tot_old]=Head_old[x],Head_old[x]=tot_old,u_old[tot_old]=x;
}
void add_new(int x,int y){
to_new[++tot_new]=y,Next_new[tot_new]=Head_new[x],Head_new[x]=tot_new,u_new[tot_new]=x;
}
int dfn[maxn],low[maxn],cnt,sta[maxn],ind,top;
bool ins[maxn];
int bel[maxn],rd[maxn],cd[maxn];
void tarjan(int x){//错误笔记:Tarjan没写instack
low[x]=dfn[x]=++ind;sta[++top]=x;ins[x]=1;
for(int i=Head_old[x];i;i=Next_old[i]){
int y=to_old[i];
if(dfn[y]){ if(ins[y]) low[x]=min(low[x],dfn[y]);}
else{
tarjan(y);low[x]=min(low[x],low[y]);
}
}
if(dfn[x]==low[x]){
++cnt;
while(sta[top]!=x){
bel[sta[top]]=cnt,ins[sta[top]]=0,top--;size[cnt]++;
}
bel[sta[top]]=cnt,top--;size[cnt]++;ins[x]=0;
}
}
set < pair<int,int> > st;
int que[maxn],rear,fro=1,copyright;
int lft;
bool str[maxn];
void toposort(){
lft=n;
for(int i=1;i<=cnt;i++){
if(!rd[i]) que[++rear]=i,--lft,str[i]=1;
}
while(fro<=rear){
int x=que[fro];++fro;
for(int i=Head_new[x];i;i=Next_new[i]){
int y=to_new[i];--rd[y];
if(!rd[y]) que[++rear]=y,--lft;
}
}
}
int cot,length;
bool vis[maxn];
int dep[maxn];
int sum[maxn];
void dfs(int x,int fa){
if(vis[x]) return;
vis[x]=1;
if(!cd[x]){
dep[x]=size[x];sum[x]=1;return;
}
for(int i=Head_new[x];i;i=Next_new[i]){
int y=to_new[i];
if(y==fa) continue;
dfs(y,x);
if(dep[y]+size[x]>dep[x]) dep[x]=dep[y]+size[x],sum[x]=sum[y]%mod;
else if(dep[y]+size[x]==dep[x]) sum[x]=(sum[x]+sum[y])%mod;
}
}
void calc(){
for(int i=1;i<=cnt;i++){
if(dep[i]>length){
length=dep[i];cot=sum[i];
}
else if(dep[i]==length){
cot=(cot+sum[i])%mod;
}
}
}
void debug_rebuild(){
puts("function debug_rebuild");
printf("Node number : %d\n",cnt);
printf("Edge number : %d\n",tot_new);
for(int i=1;i<=tot_new;i++){
printf("Edge %d u:%d v:%d\n",i,u_new[i],to_new[i]);
}
puts("\nbelong:");
for(register int i=1;i<=n;i++){
printf("Node %d belong to %d\n",i,bel[i]);
}
}
int main(){
read(n);read(m);read(mod);
for(int xx,yy,i=1;i<=m;i++){
read(xx);read(yy);add_old(xx,yy);
}
for(int i=1;i<=n;i++)
if(!dfn[i]) tarjan(i);
for(int i=1;i<=tot_old;i++){
int x=bel[u_old[i]],y=bel[to_old[i]];
if(x==y) continue;
if(st.count(make_pair(x,y))==1) continue;
st.insert(make_pair(x,y));add_new(x,y);
++rd[y];++cd[x];
}
//debug!
/* puts("");
puts("********************************************************");
puts("");
debug_rebuild();
puts("");
puts("********************************************************");
puts("");*/
//end debug
toposort();
for(int i=1;i<=cnt;i++){
if(!vis[i]&&str[i]) dfs(i,0);
}
calc();
printf("%d\n%d\n",length,cot);
return 0;
}
LG2272/BZOJ1093 「ZJOI2007」最大半连通子图 Tarjan缩点+DAG求最长链的更多相关文章
- bzoj1093: [ZJOI2007]最大半连通子图 scc缩点+dag上dp
一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向路径.若G'=(V ...
- [luogu2272 ZJOI2007] 最大半连通子图 (tarjan缩点 拓扑排序 dp)
传送门 题目描述 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向 ...
- [ZJOI2007]最大半连通子图 (Tarjan缩点,拓扑排序,DP)
题目链接 Solution 大概是个裸题. 可以考虑到,如果原图是一个有向无环图,那么其最大半联通子图就是最长的一条路. 于是直接 \(Tarjan\) 缩完点之后跑拓扑序 DP就好了. 同时由于是拓 ...
- BZOJ 1093 [ZJOI2007]最大半连通子图 - Tarjan 缩点
Description 定义一个半联通图为 : 对任意的两个点$u, v$,都有存在一条路径从$u$到$v$, 或从$v$到$u$. 给出一个有向图, 要求出节点最多的半联通子图, 并求出方案数. ...
- BZOJ1093 ZJOI2007最大半连通子图(缩点+dp)
发现所谓半连通子图就是缩点后的一条链之后就是个模板题了.注意缩点后的重边.写了1h+真是没什么救了. #include<iostream> #include<cstdio> # ...
- 【bzoj1093】[ZJOI2007]最大半连通子图 Tarjan+拓扑排序+dp
题目描述 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:对于u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向路径. ...
- BZOJ1093: [ZJOI2007]最大半连通子图(tarjan dp)
题意 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向路径.若G' ...
- BZOJ 1093: [ZJOI2007]最大半连通子图( tarjan + dp )
WA了好多次... 先tarjan缩点, 然后题意就是求DAG上的一条最长链. dp(u) = max{dp(v)} + totu, edge(u,v)存在. totu是scc(u)的结点数. 其实就 ...
- Luogu P2272 [ZJOI2007]最大半连通子图(Tarjan+dp)
P2272 [ZJOI2007]最大半连通子图 题意 题目描述 一个有向图\(G=(V,E)\)称为半连通的\((Semi-Connected)\),如果满足:\(\forall u,v\in V\) ...
随机推荐
- CF1178D Prime Graph
题目链接 题意 构造一张有\(n(3\le n\le 1000)\)个点的无向图(无重边和自环).满足: 边的总数为素数 所有点的度数均为素数 输出方案 solution 如果所有点的度数确定了.那么 ...
- npm install说明
一.常用简写 npm install=npm i.在git clone项目的时候,项目文件中并没有 node_modules文件夹,项目的依赖文件可能很大.直接执行,npm会根据package.jso ...
- 百度APP移动端网络深度优化实践分享(三):移动端弱网优化篇
本文由百度技术团队“蔡锐”原创发表于“百度App技术”公众号,原题为<百度App网络深度优化系列<三>弱网优化>,感谢原作者的无私分享. 一.前言 网络优化解决的核心问题有三个 ...
- Tsung 安装
1. Tsung是什么,有哪些特性? Tsung是一个开源.多协议.分布式的压力测试工具.它可以用来测试HTTP, WebDAV, SOAP, PostgreSQL, MySQL, LDAP 和Jab ...
- 用 qemu-user 在arm linux机器上运行amd64/x86程序
1. qemu-user 是什么 本来, 对于 QEmu, 我只知道它是一个模拟器, 可以像 VirtualBox/VMWare 那样跑一个操作系统, 只不过 QEmu 可以在 AMD64 上面跑针对 ...
- WPF ToggleButton Style
<Style x:Key="ArrowToggleStyle" TargetType="ToggleButton"> <Setter Prop ...
- 何谓SQLSERVER参数嗅探(转载)
大家听到“嗅探”这个词应该会觉得跟黑客肯定有关系吧,使用工具嗅探一下参数,然后截获,脱裤o(∩_∩)o .事实上,我觉得大家太敏感了,其实这篇文章跟数据库安全没有什么关系,实际上跟数据库性能调优有关相 ...
- Locust 接口性能测试 - 转载一 (后期熟悉实践自己出一套完整的)
转载大佬 ,.. 另外一篇:https://www.cnblogs.com/imyalost/p/9758189.html记录一下接口性能测试的学习 先熟悉一下概念: Locust是使用Pytho ...
- 【maven】搭建maven私服--基于CentOS7.6+docker
一.docker环境 Docker version 19.03.5, build 633a0ea 二.安装并启动 Maven 私服的工具: Sonatype Nexus 1.搜索 2.下载镜像 doc ...
- php 除10取整,取十位数前面一个数字,百位前两个数字
需求:php 除10取整,取十位数前面一个数字,百位前两个数字,并把大于2的加红显示 例:0-9,10-19,20-29,30-39,110-119对应为:0 1 2 3 11 实现主要方法:$num ...