[ZJOI2007]最大半连通子图

题目描述

一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向路径。若G'=(V',E')满足V'?V,E'是E中所有跟V'有关的边,则称G'是G的一个导出子图。若G'是G的导出子图,且G'半连通,则称G'为G的半连通子图。若G'是G所有半连通子图中包含节点数最多的,则称G'是G的最大半连通子图。给定一个有向图G,请求出G的最大半连通子图拥有的节点数K,以及不同的最大半连通子图的数目C。由于C可能比较大,仅要求输出C对X的余数。

输入输出格式

输入格式:

第一行包含两个整数N,M,X。N,M分别表示图G的点数与边数,X的意义如上文所述接下来M行,每行两个正整数a, b,表示一条有向边(a, b)。图中的每个点将编号为1,2,3…N,保证输入中同一个(a,b)不会出现两次。

输出格式:

应包含两行,第一行包含一个整数K。第二行包含整数C Mod X.

输入输出样例

输入样例#1:

6 6 20070603

1 2

2 1

1 3

2 4

5 6

6 4

输出样例#1:

3

3

说明

对于100%的数据, \(N \le 100000, M \le 1000000, X \le 10^8\)

Tarjan+拓扑序DP

在一个强联通分量里的点可以互相到达,所以我们先缩点,减少处理情况。

现在图变成了一张有向无环图,对于求出最多的节点数显然可以用拓扑排序求出,而对于第二问的方案数写个DP即可,具体见代码。

最近总出数组开小这种蛇皮错误qwq。

#include<bits/stdc++.h>
#define Min(a,b) (a)<(b)?(a):(b)
#define Max(a,b) (a)>(b)?(a):(b)
using namespace std;
int read()
{
int x=0,w=1;char ch=getchar();
while(ch>'9'||ch<'0') {if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*w;
}
const int N=100010;
int n,m,cnt,mod,top,visnum,scc,ans1,ans2,qwe,jishu;
int head[N],x[10*N],y[10*N],du[N];
int dfn[N],low[N],s[N],num[N],sum[N],belong[N],dp[N];
bool in[N];
struct node{
int to,next;
}edge[20*N];
struct Node{
int x,y;
}f[10*N];
queue<int>q;
bool cmp(Node p,Node q){if(p.x==q.x)return p.y<q.y;return p.x<q.x;}
void add(int x,int y)
{
cnt++;edge[cnt].to=y;edge[cnt].next=head[x];head[x]=cnt;
}
void tarjan(int k)
{
int v;
dfn[k]=low[k]=++visnum;
s[++top]=k;in[k]=1;
for(int i=head[k];i;i=edge[i].next)
{
v=edge[i].to;
if(!dfn[v])
{
tarjan(v);low[k]=Min(low[k],low[v]);
}
else if(in[v]) low[k]=Min(low[k],dfn[v]);
}
if(dfn[k]==low[k])
{
v=-1;scc++;
while(v!=k)
{
v=s[top--];in[v]=0;num[scc]++;belong[v]=scc;
}
}
}
int main()
{
n=read();m=read();mod=read();
for(int i=1;i<=m;i++)
{
x[i]=read();y[i]=read();add(x[i],y[i]);
}
for(int i=1;i<=n;i++)
{
if(!dfn[i]) tarjan(i);
}
cnt=0;memset(head,0,sizeof(head));
for(int i=1;i<=m;i++)
{
int xx=belong[x[i]],yy=belong[y[i]];
if(xx!=yy) {qwe++;f[qwe].x=xx;f[qwe].y=yy;}
}
sort(f+1,f+1+qwe,cmp);
for(int i=1;i<=qwe;i++)
{
if(f[i].x==f[i-1].x&&f[i].y==f[i-1].y) continue;
add(f[i].x,f[i].y);du[f[i].y]++;
}
for(int i=1;i<=scc;i++)
{
if(!du[i]) q.push(i),sum[i]=num[i],dp[i]=1;
}
while(q.size())
{
int u=q.front();q.pop();jishu++;
for(int i=head[u];i;i=edge[i].next)
{
int v=edge[i].to;
du[v]--;
if(sum[v]<sum[u]+num[v]) sum[v]=sum[u]+num[v],dp[v]=dp[u];
else if(sum[v]==sum[u]+num[v]) dp[v]+=dp[u];
dp[v]%=mod;
if(!du[v]) q.push(v);
}
}
for(int i=1;i<=scc;i++)
{
if(sum[ans1]<sum[i]) ans1=i,ans2=dp[i];
else if(sum[ans1]==sum[i]) ans2+=dp[i];
ans2%=mod;
}
printf("%d\n%d",sum[ans1],ans2);
}

[ZJOI2007]最大半连通子图(Tarjan,拓扑序DP)的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. bzoj 1093 最大半连通子图 - Tarjan - 拓扑排序 - 动态规划

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

  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. BZOJ1093 ZJOI2007最大半连通子图(缩点+dp)

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

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

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

  10. P2272 [ZJOI2007]最大半连通子图 tarjan+DP

    思路:$tarjan+DP$ 提交:1次 题解:首先对于一个强连通分量一定是一个半连通分量,并且形成的半连通分量的大小一定是它的$size$,所以我们先缩点. 这样,我们相当于要在新的$DAG$上找一 ...

随机推荐

  1. java生成二维码的几种方式

    1: 使用SwetakeQRCode在Java项目中生成二维码 http://swetake.com/qr/ 下载地址 或着http://sourceforge.jp/projects/qrcode/ ...

  2. js测试用

    一,大纲 二,目录二 三,目录三

  3. Mysql基本管理知识

    数据库的启动 [root@node80 ~]# /etc/init.d/mysqld start #mysqld是从安装包拷贝的mysql.server Starting MySQL. SUCCESS ...

  4. 阶段3 1.Mybatis_11.Mybatis的缓存_8 mybatis的二级缓存

    二级缓存:             它指的是Mybatis中SqlSessionFactory对象的缓存.由同一个SqlSessionFactory对象创建的SqlSession共享其缓存.      ...

  5. 测开之路一百五十三:ajax之load、get、ajax在项目中的体现

    在查询的时候是使用ajax进行请求的 目录结构 personal.models from datetime import datetimefrom flask_sqlalchemy import SQ ...

  6. ABAP基本数据类型

    ABAP 程序中共包含8种基本数据类型: 数据类型名称 描述 属  性 C Character Text(字符类型) 默认长度=1,默认值=blank,最大长度无限制 N Numeric Text(数 ...

  7. 初学node.js-nodejs中实现删除用户路由

    一.users_model.js  功能:定义用户对象模型 var mongoose=require('mongoose'), Schema=mongoose.Schema; var UserSche ...

  8. APIView的流程分析

     APIView的流程分析 1.入口,因为视图类的继承APIView()的 as_view()是一个绑定类的方法 2.进入as_view(),正好这个as_view()有个返回值 返回的是dispat ...

  9. django中的一对一的关系

    在django中一对一的关系其实就是在后面加上了unique=True 唯一的操作 源码就是这样的 其余的操作跟多对一的操作一样

  10. BindWeb - Bind智能DNS管理系统介绍

    2019-05-08 演示网站: https://bindw.cdneks.com demo/demo 2018-11-27 修改部署架构,取消网络共享存储设备,在每台BIND服务器启用NFS4并仅向 ...