问题描述

LG2272

BZOJ1093


题解

观察半联通的定义,发现图中的一些结点,构成的链一定是一个半联通子图。

此时存在的环可能会干扰求解,于是\(\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求最长链的更多相关文章

  1. 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 ...

  2. [luogu2272 ZJOI2007] 最大半连通子图 (tarjan缩点 拓扑排序 dp)

    传送门 题目描述 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向 ...

  3. [ZJOI2007]最大半连通子图 (Tarjan缩点,拓扑排序,DP)

    题目链接 Solution 大概是个裸题. 可以考虑到,如果原图是一个有向无环图,那么其最大半联通子图就是最长的一条路. 于是直接 \(Tarjan\) 缩完点之后跑拓扑序 DP就好了. 同时由于是拓 ...

  4. BZOJ 1093 [ZJOI2007]最大半连通子图 - Tarjan 缩点

    Description 定义一个半联通图为 : 对任意的两个点$u, v$,都有存在一条路径从$u$到$v$, 或从$v$到$u$. 给出一个有向图, 要求出节点最多的半联通子图,  并求出方案数. ...

  5. BZOJ1093 ZJOI2007最大半连通子图(缩点+dp)

    发现所谓半连通子图就是缩点后的一条链之后就是个模板题了.注意缩点后的重边.写了1h+真是没什么救了. #include<iostream> #include<cstdio> # ...

  6. 【bzoj1093】[ZJOI2007]最大半连通子图 Tarjan+拓扑排序+dp

    题目描述 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:对于u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向路径. ...

  7. BZOJ1093: [ZJOI2007]最大半连通子图(tarjan dp)

    题意 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向路径.若G' ...

  8. BZOJ 1093: [ZJOI2007]最大半连通子图( tarjan + dp )

    WA了好多次... 先tarjan缩点, 然后题意就是求DAG上的一条最长链. dp(u) = max{dp(v)} + totu, edge(u,v)存在. totu是scc(u)的结点数. 其实就 ...

  9. Luogu P2272 [ZJOI2007]最大半连通子图(Tarjan+dp)

    P2272 [ZJOI2007]最大半连通子图 题意 题目描述 一个有向图\(G=(V,E)\)称为半连通的\((Semi-Connected)\),如果满足:\(\forall u,v\in V\) ...

随机推荐

  1. 提高python运行效率-pypy

    pypy下载地址:https://bitbucket.org/pypy/pypy/downloads/ 如果下载太慢,去我网盘下载 https://pan.baidu.com/s/1i6j0xt0bo ...

  2. LSTM容易混淆的地方

    1 如果只是学习怎么用LSTM,那么可以这么理解LSTM LSTM可以看成一个仓库,而这个仓库有三个门卫,他们的功能分别是 遗忘门.决定什么样的物品需要从仓库中丢弃. 输入门.决定输入的什么物品用来存 ...

  3. linux jdk1.8 64位下载永久地址,ubuntu,centos,java

    https://pan.baidu.com/s/1A4cl3vUWCtiHxJ9eHK2ApQ  密码:j8dg

  4. 容器网络插件那么多,博云为什么基于OVS深度自研?

    背景 从2015年开始,博云开始基于Kubernetes和容器帮助客户交付应用管理平台.在开始阶段,博云选择了业界使用度非常广泛且成熟稳定的calico作为默认的网络方案并在calico方面积累了大量 ...

  5. tf.ConfigProto()

    tf.ConfigProto一般用在创建session的时候用来对session进行参数配置 with tf.Session(config=tf.ConfigProto(...)...) tf.Con ...

  6. XML与DataTable相互转换

    1.DataTable转XML #region DataTableToXml /// <summary> /// 将DataTable对象转换成XML字符串 /// </summar ...

  7. java截取字符串中的最后几个字符

    Java中的String类提供了一个substring(int from, int to)方法用于截取字符串中位置为from到to-1位置的字符. 因为字符串的字符位置是从0开始的,而substrin ...

  8. 使用 PDBDownloader 解决 IDA 加载 ntoskrnl.exe 时符号不完全问题

    解决 IDA 加载 ntoskrnl.exe 时符号不完全问题 1. 问题:IDA加载xp系统的 ntoskrnl.exe 加载不完全. 2. 尝试过但未成功的解决方案: 1)配置好的IDA的 pdb ...

  9. SqlServer 开篇简介

    实例:我们的电脑中可以安装一个或多个SqlServer实例,每一个SqlServer实例可以包含一个或者多个数据库. 架构:数据库中,又有一个或者多个架构.架构里面包含:表,视图,存储过程. 文件与文 ...

  10. .net webapi跨域问题

    2019年11月8日,近期做项目开始实行前后端分离的方式开发,前端使用vue的框架,打包发布后,调用后端接口出现跨域的问题,网上搜索出来的都是以下的配置方式: 但是,在我的项目中,按这种方式配置没有效 ...