bzoj 1093 最大半连通子图 - Tarjan - 拓扑排序 - 动态规划
一个有向图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的余数。
Input
第一行包含两个整数N,M,X。N,M分别表示图G的点数与边数,X的意义如上文所述接下来M行,每行两个正整数a, b,表示一条有向边(a, b)。图中的每个点将编号为1,2,3…N,保证输入中同一个(a,b)不会出现两次。N ≤100000, M ≤1000000;对于100%的数据, X ≤10^8
Output
应包含两行,第一行包含一个整数K。第二行包含整数C Mod X.
Sample Input
6 6 20070603
1 2
2 1
1 3
2 4
5 6
6 4
Sample Output
3
3
题目大意 一个有向图G(V, U)是半连通的,当且仅当任意点
,并且存在一条路径,它上面的所有边属于U,并且从u到v或者从v到u。图G的导出子图G‘(V'. U'),满足
.一个有向图G的半连通子图是一个导出子图且半连通,最大半连通子图是其中拥有最多点数的半连通子图。问最大的半连通子图的点数和数量。
因为半连通子图一定是导出子图,所以两个半连通子图是否同构之和它们的定点集合有关。
由于图上可能有环(强连通分量),所以考虑缩点。缩点后的图是个DAG,然后你可得到一个结论就是这个DAG上的一条路径就是原图的一个半连通子图,并且DAG上的路径和原图中的半连通子图一一对应。
我们可以赋予每个点一个点权,代表它在原图中代表的点数。
于是这个问题转换成在DAG上最长路及其计数。这个拓扑排序再加个小dp就可以水过了。
另外注意拓扑排序的时判断重边。
Code
/**
* bzoj
* Problem#1093
* Accepted
* Time: 1988ms
* Memory: 13740k
*/
#include <bits/stdc++.h>
using namespace std;
typedef bool boolean;
#define smin(a, b) a = min(a, b)
#define smax(a, b) b = max(a, b) int n, m;
int moder;
vector<int> *g; inline void init() {
scanf("%d%d%d", &n, &m, &moder);
g = new vector<int>[(n + )];
for(int i = , u, v; i <= m; i++) {
scanf("%d%d", &u, &v);
g[u].push_back(v);
}
} int cnt = ;
stack<int> s;
int* visitID;
int* exitID;
int* belong;
boolean *visited;
boolean *instack;
inline void init_tarjan() {
visitID = new int[(n + )];
exitID = new int[(n + )];
visited = new boolean[(n + )];
instack = new boolean[(n + )];
belong = new int[(n + )];
memset(visited, false, sizeof(boolean) * (n + ));
memset(instack, false, sizeof(boolean) * (n + ));
} void tarjan(int node) {
visitID[node] = exitID[node] = ++cnt;
visited[node] = instack[node] = true;
s.push(node); for(int i = ; i < (signed)g[node].size(); i++) {
int& e = g[node][i];
if(!visited[e]) {
tarjan(e);
smin(exitID[node], exitID[e]);
} else if(instack[e]) {
smin(exitID[node], visitID[e]);
}
} if(visitID[node] == exitID[node]) {
int e;
do {
e = s.top();
s.pop();
instack[e] = false;
belong[e] = node;
} while(e != node);
}
} vector<int> *ng;
int* dag;
int *val;
inline void rebuild() {
dag = new int[(n + )];
ng = new vector<int>[(n + )];
val = new int[(n + )];
memset(val, , sizeof(int) * (n + ));
memset(dag, , sizeof(int) * (n + )); for(int i = ; i <= n; i++)
for(int j = ; j < (signed)g[i].size(); j++) {
int& e = g[i][j];
if(belong[e] != belong[i])
ng[belong[i]].push_back(belong[e]), dag[belong[e]]++;
} for(int i = ; i <= n; i++)
val[belong[i]]++;
} queue<int> que;
int *dis;
int *counter;
inline void topu() {
dis = new int[(n + )];
counter = new int[(n + )];
memset(dis, , sizeof(int) * (n + ));
memset(visited, false, sizeof(boolean) * (n + )); for(int i = ; i <= n; i++)
if(belong[i] == i && !dag[i])
que.push(i), dis[i] = val[i], counter[i] = ; while(!que.empty()) {
int e = que.front();
que.pop();
for(int i = ; i < (signed)ng[e].size(); i++) {
int& eu = ng[e][i];
dag[eu]--;
if(!dag[eu])
que.push(eu);
if(visited[eu]) continue;
visited[eu] = true; if(dis[e] + val[eu] > dis[eu]) {
dis[eu] = dis[e] + val[eu];
counter[eu] = counter[e];
} else if(dis[e] + val[eu] == dis[eu])
counter[eu] = (counter[eu] + counter[e]) % moder;
}
for(int i = ; i < (signed)ng[e].size(); i++)
visited[ng[e][i]] = false;
}
} int maxdis = -, res = ;
inline void solve() {
for(int i = ; i <= n; i++) {
if(belong[i] != i) continue;
if(dis[i] > maxdis) {
maxdis = dis[i];
res = counter[i];
} else if(dis[i] == maxdis)
(res += counter[i]) %= moder;
}
printf("%d\n%d", maxdis, res);
} int main() {
init();
init_tarjan();
for(int i = ; i <= n; i++)
if(!visited[i])
tarjan(i);
rebuild();
topu();
solve();
return ;
}
bzoj 1093 最大半连通子图 - Tarjan - 拓扑排序 - 动态规划的更多相关文章
- 【bzoj1093】[ZJOI2007]最大半连通子图 Tarjan+拓扑排序+dp
题目描述 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:对于u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向路径. ...
- BZOJ 1093 最大半连通子图 题解
1093: [ZJOI2007]最大半连通子图 Time Limit: 30 Sec Memory Limit: 162 MBSubmit: 2767 Solved: 1095[Submit][S ...
- [BZOJ]1093 最大半连通子图(ZJOI2007)
挺有意思的一道图论. Description 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:∀u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v ...
- BZOJ 1093 最大半连通子图
缩点求最长链. #include<iostream> #include<cstdio> #include<cstring> #include<algorith ...
- BZOJ 1093: [ZJOI2007]最大半连通子图( tarjan + dp )
WA了好多次... 先tarjan缩点, 然后题意就是求DAG上的一条最长链. dp(u) = max{dp(v)} + totu, edge(u,v)存在. totu是scc(u)的结点数. 其实就 ...
- [luogu2272 ZJOI2007] 最大半连通子图 (tarjan缩点 拓扑排序 dp)
传送门 题目描述 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向 ...
- BZOJ1093: [ZJOI2007]最大半连通子图(tarjan dp)
题意 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向路径.若G' ...
- Luogu P2272 [ZJOI2007]最大半连通子图(Tarjan+dp)
P2272 [ZJOI2007]最大半连通子图 题意 题目描述 一个有向图\(G=(V,E)\)称为半连通的\((Semi-Connected)\),如果满足:\(\forall u,v\in V\) ...
- [ZJOI2007]最大半连通子图 (Tarjan缩点,拓扑排序,DP)
题目链接 Solution 大概是个裸题. 可以考虑到,如果原图是一个有向无环图,那么其最大半联通子图就是最长的一条路. 于是直接 \(Tarjan\) 缩完点之后跑拓扑序 DP就好了. 同时由于是拓 ...
随机推荐
- Xception网络结构理解
Xception网络是由inception结构加上depthwise separable convlution,再加上残差网络结构改进而来/ 常规卷积是直接通过一个卷积核把空间信息和通道信息直接提取出 ...
- 41.SEO----前端SEO技巧
一.搜索引擎工作原理 当我们在输入框中输入关键词,点击搜索或查询时,然后得到结果.深究其背后的故事,搜索引擎做了很多事情. 在搜索引擎网站,比如百度,在其后台有一个非常庞大的数据库,里面存储了海量的关 ...
- laravel中使用event
https://www.cnblogs.com/ziyouchutuwenwu/p/4274539.html
- XML小结
一.因为某些字符在xml格式中,具有特殊意义,所以当我们需要使用它本身的意思的时候,就要用其他东西来代替它,否则会产生错误 < < less than > > greater ...
- armv8 memory translation table descriptor
上一节大致给出了descriptor的结构,这篇细致分析各个field: 1) Table Descriptor:stage2中不包含任何的attribute的field,每个level中的descr ...
- report源码分析——宏的执行
uvm_info,uvm_error其实是对uvm_report_info,uvm_report_error的封装. 其中warning,error,fatal,macros默认都是定义为UVM_NO ...
- tensorflow tensor 索引
问题: self.q_eval4next: (100,2) ix=[0,1,0,1---0,1](100,1) 我想取q_eval4next[:,idx] #use_doubleQ 切片用!!!! s ...
- html5-css的使用强制优先级
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8&qu ...
- hdu4746莫比乌斯反演+分块
http://blog.csdn.net/mowayao/article/details/38875021 题意: 5000组样例. 问你[1,n] 和 [1,m]中有多少对数的GCD的素因子个数小于 ...
- SITECORE体验编辑器 - 多站点实施站点解析
SITECORE体验编辑器 - 多站点实施站点解析 我们使用其中一个多站点实现遇到了Sitecore体验编辑器的问题.从内容编辑器中选择并尝试在体验编辑器中打开时属于某个站点的任何页面将始终解析为 ...