题目描述

一个有向图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.

说明/提示

对于100%的数据,N<=100000, M<=1000000, X<=1e8

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int mod;
const int N=2e5+10,M=2e6+10;
int next[M],head[N],go[M],tot;
inline void add(int u,int v){
next[++tot]=head[u];head[u]=tot;go[tot]=v;
}
int dfn[N],low[N],co[N],st[N],sz[N],top,num,col;
inline void Tarjan(int u){
dfn[u]=low[u]=++num;
st[++top]=u;
for(int i=head[u];i;i=next[i]){
int v=go[i];
if(!dfn[v]){
Tarjan(v);
low[u]=min(low[u],low[v]);
}else if(!co[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(dfn[u]==low[u]){
co[u]=++col;
sz[col]=1;
while(st[top]!=u){
co[st[top]]=col;
sz[col]++;
--top;
}
--top;
}
} struct E{
int u,v;
}e[M];
int in[N];
int n,m;
struct node{
int u,dat;
};
int dis[N],dp[N];
inline void topsort(){
queue<int>q;
for(int i=1;i<=col;i++){
if(!in[i])q.push(i);
dis[i]=sz[i],dp[i]=1;
}
while(q.size()){
int u=q.front();q.pop();
for(register int i=head[u];i;i=next[i]){
int v=go[i];
if(dis[v]<dis[u]+sz[v]){
dis[v]=dis[u]+sz[v];
dp[v]=dp[u];
}else if(dis[v]==dis[u]+sz[v]){
dp[v]=(dp[v]+dp[u])%mod;
}
--in[v];
if(in[v]==0)q.push(v);
}
}
int ans1=0,ans2=0;
for(int i=1;i<=col;i++){
if(dis[i]==ans1)
ans2=(ans2+dp[i])%mod;
if(dis[i]>ans1)
ans1=dis[i],ans2=dp[i];
}
cout<<ans1<<endl<<ans2;
}
bool cmp(E t1,E t2){
if(co[t1.u]==co[t2.u])return co[t1.v]<co[t2.v];
else return co[t1.u]<co[t2.u];
}
signed main(){ cin>>n>>m>>mod;
for(int i=1,u,v;i<=m;i++){
scanf("%d%d",&u,&v);
e[i]=(E){u,v};
add(u,v);
}
for(int i=1;i<=n;i++)
if(!dfn[i])Tarjan(i);
memset(next,0,sizeof(next));
memset(head,0,sizeof(head));
memset(go,0,sizeof(go)),tot=0;
sort(e+1,e+1+m,cmp);
for(int i=1;i<=m;i++){
if(co[e[i].u]==co[e[i-1].u]&&co[e[i].v]==co[e[i-1].v])continue;
if(co[e[i].u]!=co[e[i].v])
add(co[e[i].u],co[e[i].v]),in[co[e[i].v]]++;
}
topsort();
}

luogu P2272 [ZJOI2007]最大半连通子图的更多相关文章

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

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

  2. 洛谷 P2272 [ZJOI2007]最大半连通子图 解题报告

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

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

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

  4. P2272 [ZJOI2007]最大半连通子图

    思路 tarjan的题目 注意是要选出一个点集而不是边集 第一问就是缩点之后最长链,第二问就是有多少个最长链,注意缩点后连边要去重(不然一个链的方案可能会被统计多次) 代码 #include < ...

  5. 题解 P2272 【[ZJOI2007]最大半连通子图】

    P2272 [ZJOI2007]最大半连通子图 萌新初学Tarjan,在<信息学奥赛一本通-提高篇>中看到这题,看到题解不多,便想发布一篇较为清新简洁的题解.--第5道紫题 题目大意: 定 ...

  6. BZOJ 1093 [ZJOI2007] 最大半连通子图(强联通缩点+DP)

    题目大意 题目是图片形式的,就简要说下题意算了 一个有向图 G=(V, E) 称为半连通的(Semi-Connected),如果满足图中任意两点 u v,存在一条从 u 到 v 的路径或者从 v 到 ...

  7. BZOJ 1093 [ZJOI2007]最大半连通子图

    1093: [ZJOI2007]最大半连通子图 Time Limit: 30 Sec  Memory Limit: 162 MBSubmit: 1986  Solved: 802[Submit][St ...

  8. bzoj 1093 [ZJOI2007]最大半连通子图(scc+DP)

    1093: [ZJOI2007]最大半连通子图 Time Limit: 30 Sec  Memory Limit: 162 MBSubmit: 2286  Solved: 897[Submit][St ...

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

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

随机推荐

  1. jquery倒计时代码

    jquery倒计时代码<pre> <span id="day_show">0天</span> <strong id="hour_ ...

  2. 从多维卷积说起,比较CNN中的全连接和全卷积

    一幅图像里包含三个通道,分别是RGB通道.三通道在卷积时是通过累加三个卷积结果得到的. CNN中全连接层的卷积核大小是feature map的大小.比如feature是3*3的,那么该全连接层的卷积核 ...

  3. Python之tkinter.messagebox弹窗

    messagebox:tkinter的消息框.对话框 一.messagebox.showinfo(title='提示', message='错误') from tkinter import * fro ...

  4. 语义分割学习之SegNet的C++编译

    Abstract 安装好Segnet并使用Python进行训练和测试之后,考虑项目的应用,需要在C++的工程环境下进行继续开发,所以这里的主要内容是用C++建立工程,使用相应的数据集和权重参数文件进行 ...

  5. 领扣(LeetCode)单调数列 个人题解

    如果数组是单调递增或单调递减的,那么它是单调的. 如果对于所有 i <= j,A[i] <= A[j],那么数组 A 是单调递增的. 如果对于所有 i <= j,A[i]> = ...

  6. TreeMap的源码学习

    TreeMap的源码学习 一).TreeMap的特点 根据key值进行排序. 二).按key值排序的两种排序算法实现 1).在构造方法中传入比较器 public TreeMap(Comparator& ...

  7. Ubuntu 16.04安装ROS Kinetic详细教程 | Tutorial to Install and Configure ROS Kinetic on Ubuntu 16.04

    本文首发于个人博客https://kezunlin.me/post/e2780b93/,欢迎阅读! Tutorial to Install and Configure ROS Kinetic on U ...

  8. 在idea中使用git

    在idea中使用git 1. 在idea中配置git ​ 安装好IntelliJ IDEA后,如果Git安装在默认路径下,那么idea会自动找到git的位置,如果更改了Git的安装位置则需要手动配置下 ...

  9. Redis 数据结构

    一.Redis简介 Redis是一款基于key-value的高性能NoSQL数据库,开源免费,遵守BSD协议.支持string(字符串) . hash(哈希) .list(列表) . set(集合) ...

  10. Eclipse设置Working Set管理项目和detach合并分离窗口

    当项目多了的时候,使用Working Set分组管理项目很有必要了,不然一大推项目在一起 找起来麻烦,看起来也难受~ ​ 所以根据给项目不同分类就很有必要了. 之前myeclipse设置了,今天装了一 ...