bzoj 1093 [ZJOI2007]最大半连通子图(scc+DP)
1093: [ZJOI2007]最大半连通子图
Time Limit: 30 Sec Memory Limit: 162 MB
Submit: 2286 Solved: 897
[Submit][Status][Discuss]
Description

Input
第一行包含两个整数N,M,X。N,M分别表示图G的点数与边数,X的意义如上文所述。接下来M行,每行两个正整数a, b,表示一条有向边(a, b)。图中的每个点将编号为1,2,3…N,保证输入中同一个(a,b)不会出现两次。
Output
应包含两行,第一行包含一个整数K。第二行包含整数C Mod X.
Sample Input
1 2
2 1
1 3
2 4
5 6
6 4
Sample Output
3
HINT
对于100%的数据, N ≤100000, M ≤1000000;对于100%的数据, X ≤10^8。
Source
【思路】
强连通分量+拓扑排序+DP
求scc,锁点。则问题转化为求DAG上的最长路,在拓扑序上进行DP即可。
需要注意的是重新构图的时候会有重边,为了防止重复计数需要特别处理一下。
【代码】
#include<cstdio>
#include<stack>
#include<queue>
#include<vector>
#include<cstring>
#include<iostream>
using namespace std; const int maxn = +; vector<int> g[maxn],G[maxn];
int pre[maxn],lowlink[maxn],sccno[maxn],scccnt,dfsclock;
stack<int> S; int dfs(int u) {
pre[u]=lowlink[u]=++dfsclock;
S.push(u);
for(int i=;i<g[u].size();i++) {
int v=g[u][i];
if(!pre[v]) {
dfs(v);
lowlink[u]=min(lowlink[u],lowlink[v]);
}
else if(!sccno[v]) {
lowlink[u]=min(lowlink[u],pre[v]);
}
}
if(lowlink[u]==pre[u]) {
++scccnt;
for(;;) {
int x=S.top() ; S.pop();
sccno[x]=scccnt;
if(x==u) break;
}
}
}
void findscc(int n) {
memset(pre,,sizeof(pre));
memset(sccno,,sizeof(sccno));
dfsclock=scccnt=;
for(int i=;i<n;i++)
if(!pre[i]) dfs(i);
} int n,m,MOD;
int d[maxn],cnt[maxn]; int val[maxn],in[maxn];
void build() {
for(int i=;i<n;i++) {
val[sccno[i]]++;
for(int j=;j<g[i].size();j++) {
int v=g[i][j];
if(sccno[i]==sccno[v]) continue;
in[sccno[v]]++;
G[sccno[i]].push_back(sccno[v]);
}
}
}
void solve() {
queue<int> q;
int vis[maxn];
for(int i=;i<=scccnt;i++) if(!in[i]) {
d[i]=val[i] , cnt[i]=;
q.push(i);
}
while(!q.empty()) {
int u=q.front(); q.pop();
for(int i=;i<G[u].size();i++) {
int v=G[u][i];
if(!(--in[v])) q.push(v);
if(vis[v]!=u) { //重新构图后有重边 防止重复计数
if(d[v]<d[u]+val[v]) {
d[v]=d[u]+val[v]; cnt[v]=cnt[u];
}
else if(d[v]==d[u]+val[v])
cnt[v]=(cnt[v]+cnt[u])%MOD;
}
vis[v]=u;
}
}
} int main() {
scanf("%d%d%d",&n,&m,&MOD);
int u,v;
while(m--) {
scanf("%d%d",&u,&v);
u-- , v--;
g[u].push_back(v);
}
findscc(n);
build();
solve();
int ans=,ansnum=;
for(int i=;i<=scccnt;i++)
if(ans<d[i]) ans=d[i] , ansnum=cnt[i];
else if(ans==d[i]) ansnum=(ansnum+cnt[i])%MOD;
printf("%d\n%d",ans,ansnum);
return ;
}
bzoj 1093 [ZJOI2007]最大半连通子图(scc+DP)的更多相关文章
- BZOJ 1093: [ZJOI2007]最大半连通子图( tarjan + dp )
WA了好多次... 先tarjan缩点, 然后题意就是求DAG上的一条最长链. dp(u) = max{dp(v)} + totu, edge(u,v)存在. totu是scc(u)的结点数. 其实就 ...
- 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]最大半连通子图
Description 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意 两点u,v,存在一条u到v的有向路径或者从v到 ...
- BZOJ 1093 [ZJOI2007]最大半连通子图 - Tarjan 缩点
Description 定义一个半联通图为 : 对任意的两个点$u, v$,都有存在一条路径从$u$到$v$, 或从$v$到$u$. 给出一个有向图, 要求出节点最多的半联通子图, 并求出方案数. ...
- bzoj 1093 [ZJOI2007]最大半连通子图——缩点+拓扑
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1093 缩点+拓扑,更新长度的时候维护方案数. 结果没想到处理缩点后的重边,这样的话方案数会算 ...
- bzoj 1093: [ZJOI2007]最大半连通子图【tarjan+拓扑排序+dp】
先tarjan缩成DAG,然后答案就变成了最长链,dp的同时计数即可 就是题面太唬人了,没反应过来 #include<iostream> #include<cstdio> #i ...
- Luogu P2272 [ZJOI2007]最大半连通子图(Tarjan+dp)
P2272 [ZJOI2007]最大半连通子图 题意 题目描述 一个有向图\(G=(V,E)\)称为半连通的\((Semi-Connected)\),如果满足:\(\forall u,v\in V\) ...
- 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 ...
随机推荐
- 版本控制-cvs
我们实训用的是cvs. 团队协作: 代码版本控制软件:CVS.SVN.GIT(Git@开源中国) FTP:服务端.客户端 CVS: 服务端(源码仓库).客户端
- 内存储与外存储(IO流的应用)
存储分为内存储,外存储(Sd卡存储),其中还涉及IO流的应用. 我们先来看内存储,在布局中EditView中输入的内容,通过点击按钮,分别进行保存,读取,删除的操作,读取时显示在下面的TextView ...
- Android 通信机制Message、Handler 的用法
Android中提供了通信机制,Message.Handler 等,Message用于在子线程中传递数据,Handler用于发送数据到主线程中, 下面介绍基于Message.Handler的计时器 i ...
- 40个DBA日常维护的SQL脚本--1113
from itpub --1.查询碎片程度高的表--条件为什么block>100,因为一些很小的表,只有几行数据实际大小很小,但是block一次性分配就是5个(11g开始默认一次性分配1M的bl ...
- Android的进程和线程(转)
进程和线程 当一个应用程序第一次启动的时候,Android会启动一个Linux进程和一个主线程(即UI线程:主要负责处理用户的按键事件.触屏事件及屏幕绘图事件等).默认情况下,所有该程序的组件都将在该 ...
- jquery中eq和get的区别与使用方法
$("p").eq(0).css("color") //因为eq(num)返回的是个jq对象,所以可以用jq的方法css使用get来获得第一个p标签的color ...
- web版扫雷小游戏(二)
接上篇~~第一次写这种技术博客,发现把自己做的东西介绍出来还是一件脑力活,不是那么轻松啊,好吧,想到哪写到哪,流水记录之,待完成之后再根据大家的意见进行修改吧. 游戏实现 根据对扫雷游戏的体验和分析, ...
- 深入解析.NET框架
一.AOP框架 Encase 是C#编写开发的为.NET平台提供的AOP框架.Encase 独特的提供了把方面(aspects)部署到运行时代码,而其它AOP框架依赖配置文件的方式.这种 ...
- HTML5拖放API
拖放事件事件提供了拖放可以控制几乎所有方面的拖放操作.棘手的部分是确定每个事件触发:在拖项目火:别人火下降的目标.拖动项时,以下事件(按照这个顺序): 拖曳开始拖dragend此刻你把鼠标按钮和开始移 ...
- Java常量和变量
1.Java运行原理 编译+解释型语言: 程序代码经编译后转换为一种称为java字节码(.class文件)的中间语言 file.java--->Class.class java虚拟机JVM将字节 ...