洛谷 P2272 [ZJOI2007]最大半连通子图 解题报告
P2272 [ZJOI2007]最大半连通子图
题目描述
一个有向图\(G=(V,E)\)称为半连通的\((Semi-Connected)\),如果满足:\(\forall u,v \in V\),满足\(u \to v\)或\(v \to u\),即对于图中任意两点\(u\),\(v,\)存在一条\(u\)到\(v\)的有向路径或者从\(v\)到\(u\)的有向路径。若\(G'=(V',E')\)满足\(V' \in 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 \le 100000, M \le 1000000, X \le 10^8\)
这种题先缩点都成套路了吧
考虑在一个有向无环图中半联通图是什么,结果是一条链,直接做DP就行了
但是!!
这个题一定要考虑重边
Code:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define ll long long
using namespace std;
const int N=100010;
const int M=1000010;
int head0[N],Next0[M],to0[M],cnt0;
void add0(int u,int v)
{
Next0[++cnt0]=head0[u];to0[cnt0]=v;head0[u]=cnt0;
}
int head[N],Next[M],to[M],cnt;
void add(int u,int v)
{
Next[++cnt]=head[u];to[cnt]=v;head[u]=cnt;
}
int dfn[N],low[N],in[N],s[N],ha[N],siz[N],time,tot;
int n,m,n_,cntt;
ll p;
pair <int,int > e[M];
void tarjan(int now)
{
dfn[now]=low[now]=++time;
s[++tot]=now;
in[now]=1;
for(int i=head0[now];i;i=Next0[i])
{
int v=to0[i];
if(!dfn[v])
{
tarjan(v);
low[now]=min(low[now],low[v]);
}
else if(in[v])
low[now]=min(low[now],dfn[v]);
}
if(low[now]==dfn[now])
{
int k,Siz=0;
n_++;
do
{
k=s[tot--];
Siz++;
ha[k]=n_;
in[k]=0;
}while(k!=now);
siz[n_]=Siz;
}
}
void New()
{
for(int i=1;i<=n;i++)
{
for(int j=head0[i];j;j=Next0[j])
{
int v=to0[j];
if(ha[v]!=ha[i])
e[++cntt]=make_pair(ha[i],ha[v]);
}
}
sort(e+1,e+1+cntt);
cntt=unique(e+1,e+1+cntt)-(e+1);
for(int i=1;i<=cntt;i++)
{
in[e[i].second]++;
add(e[i].first,e[i].second);
}
}
void init()
{
scanf("%d%d%lld",&n,&m,&p);
int u,v;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
add0(u,v);
}
for(int i=1;i<=n;i++)
if(!dfn[i])
tarjan(i);
memset(in,0,sizeof(in));
New();
}
ll Cnt[N],ans;
int dp[N],mx;
queue <int > q;
void work()
{
for(int i=1;i<=n_;i++)
if(!in[i])
{
q.push(i);
dp[i]=siz[i];
mx=max(mx,dp[i]);
Cnt[i]=1;
}
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=head[u];i;i=Next[i])
{
int v=to[i];
if(dp[v]<dp[u]+siz[v])
{
dp[v]=dp[u]+siz[v];
Cnt[v]=Cnt[u];
mx=max(mx,dp[v]);
}
else if(dp[v]==dp[u]+siz[v])
(Cnt[v]+=Cnt[u])%=p;
in[v]--;
if(!in[v]) q.push(v);
}
}
for(int i=1;i<=n_;i++)
if(dp[i]==mx)
(ans+=Cnt[i])%=p;
printf("%d\n%lld\n",mx,ans);
}
int main()
{
init();
work();
return 0;
}
2018.7.26
洛谷 P2272 [ZJOI2007]最大半连通子图 解题报告的更多相关文章
- BZOJ1093或洛谷2272 [ZJOI2007]最大半连通子图
BZOJ原题链接 洛谷原题链接 和 Going from u to v or from v to u?(题解)这道题类似,只不过是求最大子图的大小和个数而已. 一样用\(tarjan\)求强连通分量, ...
- Luogu P2272 [ZJOI2007]最大半连通子图(Tarjan+dp)
P2272 [ZJOI2007]最大半连通子图 题意 题目描述 一个有向图\(G=(V,E)\)称为半连通的\((Semi-Connected)\),如果满足:\(\forall u,v\in V\) ...
- luogu P2272 [ZJOI2007]最大半连通子图
题目描述 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向路径.若 ...
- P2272 [ZJOI2007]最大半连通子图 tarjan+DP
思路:$tarjan+DP$ 提交:1次 题解:首先对于一个强连通分量一定是一个半连通分量,并且形成的半连通分量的大小一定是它的$size$,所以我们先缩点. 这样,我们相当于要在新的$DAG$上找一 ...
- P2272 [ZJOI2007]最大半连通子图
思路 tarjan的题目 注意是要选出一个点集而不是边集 第一问就是缩点之后最长链,第二问就是有多少个最长链,注意缩点后连边要去重(不然一个链的方案可能会被统计多次) 代码 #include < ...
- 题解 P2272 【[ZJOI2007]最大半连通子图】
P2272 [ZJOI2007]最大半连通子图 萌新初学Tarjan,在<信息学奥赛一本通-提高篇>中看到这题,看到题解不多,便想发布一篇较为清新简洁的题解.--第5道紫题 题目大意: 定 ...
- BZOJ 1093 [ZJOI2007] 最大半连通子图(强联通缩点+DP)
题目大意 题目是图片形式的,就简要说下题意算了 一个有向图 G=(V, E) 称为半连通的(Semi-Connected),如果满足图中任意两点 u v,存在一条从 u 到 v 的路径或者从 v 到 ...
- BZOJ 1093 [ZJOI2007]最大半连通子图
1093: [ZJOI2007]最大半连通子图 Time Limit: 30 Sec Memory Limit: 162 MBSubmit: 1986 Solved: 802[Submit][St ...
- bzoj 1093 [ZJOI2007]最大半连通子图(scc+DP)
1093: [ZJOI2007]最大半连通子图 Time Limit: 30 Sec Memory Limit: 162 MBSubmit: 2286 Solved: 897[Submit][St ...
随机推荐
- 「功能笔记」性能分析工具gprof使用笔记
根据网上信息整理所成. 功能与优劣 gprof实际上只是一个用于读取profile结果文件的工具.gprof采用混合方法来收集程序的统计信息,它使用检测方法,在编译过程中在函数入口处插入计数器用于收集 ...
- sqlserver错误126解决方法
是不是很尴尬! 华丽的分割线下便是解决方法: 1.打开sqlserver配置管理器. 2.选择sqlserver网络配置,并禁用VIA协议确定保存. 3.在服务里面启动[SQL Server (SQL ...
- (C#)设计模式之状态模式
1.状态模式 当一个对象的内在状态改变时允许改变其行为,这个对象看起像是改变了其类. *状态模式主要解决的是当控制一个对象的状态转换的条件表达式过于复杂时,可以将状态的判断逻辑转移到表示不同状态的一系 ...
- python中为什么 if/while/def/class语句需要冒号?
python中冒号主要用于增强可读性(ABC语言实验的结果之一).考虑一下这个: if a == b print(a) 与 if a == b: print(a) 注意第二种方法稍微容易一些.请进一步 ...
- vue中如何实现pdf文件预览?
今天产品提出一个优化的需求,就是之前我们做的图片展示就是一个img标签搞定,由于我们做的是海外后台管理系统,那边的人上传的文件时pdf格式,vue本事是不支持这种格式文件展示的,于是就google搜索 ...
- 四分树 (Quadtrees UVA - 297)
题目描述: 原题:https://vjudge.net/problem/UVA-297 题目思路: 1.依旧是一波DFS建树 //矩阵实现 2.建树过程用1.0来填充表示像素 #include < ...
- [Clr via C#读书笔记]Cp7常量和字段
Cp7常量和字段 常量 常量在编译的时候必须确定,只能一编译器认定的基元类型.被视为静态,不需要static:直接嵌入IL中: 区别ReadOnly 只能在构造的时候初始化,内联初始化. 字段 数据成 ...
- 在本地电脑使用远程服务器的图形界面——包括 MATLAB、PyCharm 等各种软件
在用本地电脑连接远程服务器的时候,大部分时候只能用命令行来操作.虽然可以 在本地电脑用 PyCharm 进行远程调试.在本地电脑远程使用服务器的 Jupyter Notebook.Ubuntu 和 W ...
- @ConfigurationProperties注解对数据的自动封装
@ConfigurationProperties注解对数据的自动封装 @ConfigurationProperties可以对基本数据类型实现自动封装,可以封装格式为yyyy/MM/dd的日期 测试代码 ...
- KVM存储虚拟化---玩转openstack
KVM 的存储虚拟化是通过存储池(Storage Pool)和卷(Volume)来管理的. Storage Pool 是宿主机上可以看到的一片存储空间,可以是多种类型,后面会详细讨论.Volume 是 ...