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\) ...
随机推荐
- map 基本使用
package main import "fmt" func main(){ //定义一个map变量,类型为map[int]string,如果使用map一定初始化,make分配空间 ...
- Note | PyTorch
目录 0. 教程和笔记 1. 模型操作 2. 网络设计 卷积图示 填充(padding) 升采样 全连接层 3. 损失函数 交叉熵 4. 系统或环境交互 模型加载 5. 犯过的错误 损失异常 测试显存 ...
- Qt 删掉资源qss后报错
Error: dependent '..\..\........XXXX.qss' does not exist. 解决方案: 1.清理工程 2.qmake 3.重新构建
- 软件工程实践2019——idea表述及组队
时间:2019-10-08 随堂 欢迎每个有想法的同学都积极参与idea表述,用心呈现你的心中所想.你心中热爱的,希望在软工实践项目中完成的项目作品.每个愿意表达idea的同学,都有一分钟时间来呈现作 ...
- CentOS设置主机名称
1.查看主机名,使用命令hostname: 2.修改主机名,修改/etc/hostname文件
- jre、jdk、jvm之间的关系
很多Java的程序员在写了很多代码之后,你问他JRE和JDK是是什么关系,JVM又是什么东西,他是不知道的. JVM(Java Virtual Machine) Java 虚拟机.它只认识 xxx.c ...
- 在Visual Studio 中使用 <AutoGenerateBindingRedirects> 来解决引用的程序集版本冲突问题
问题: https://stackoverflow.com/questions/42836248/using-autogeneratebindingredirects-in-visual-studio ...
- Spring源码系列 — BeanDefinition
一.前言 回顾 在Spring源码系列第二篇中介绍了Environment组件,后续又介绍Spring中Resource的抽象,但是对于上下文的启动过程详解并未继续.经过一个星期的准备,梳理了Spri ...
- 何谓SQLSERVER参数嗅探(转载)
大家听到“嗅探”这个词应该会觉得跟黑客肯定有关系吧,使用工具嗅探一下参数,然后截获,脱裤o(∩_∩)o .事实上,我觉得大家太敏感了,其实这篇文章跟数据库安全没有什么关系,实际上跟数据库性能调优有关相 ...
- ASP.NET MVC 中枚举生成下拉框
最近公司在开发财务系统,在工作中遇到不少的地方需要下拉框. 但是枚举框中数据的内容又来自枚举. 枚举代码如下: public class EnumDemo { public enum Value { ...