WA了好多次...

先tarjan缩点, 然后题意就是求DAG上的一条最长链. dp(u) = max{dp(v)} + totu, edge(u,v)存在. totu是scc(u)的结点数. 其实就是记忆化搜一下...重边就用set判一下

-------------------------------------------------------------------------------------------

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#include<iostream>
#include<cctype>
#include<set>
 
using namespace std;
 
const int maxn = 100009;
const int INF = 0x3F3F3F3F;
 
inline int read() {
char c = getchar();
int ret = 0;
for(; !isdigit(c); c = getchar());
for(; isdigit(c); c = getchar()) ret = ret * 10 + c - '0';
return ret;
}
 
struct edge {
int to;
edge* next;
} E[1000009], *pt = E, *head[maxn];
 
void addedge(int u, int v) {
pt->to = v; pt->next = head[u]; head[u] = pt++;
}
 
int N, scc[maxn], dfn[maxn], low[maxn], tot[maxn], CK = 0, n = -1, MOD;
stack<int> S;
set<pair<int, int> > bst;
 
void tarjan(int x) {
dfn[x] = low[x] = ++CK;
S.push(x);
for(edge* e = head[x]; e; e = e->next)
if(!dfn[e->to])
tarjan(e->to), low[x] = min(low[e->to], low[x]);
else if(!~scc[e->to])
low[x] = min(low[x], dfn[e->to]);
if(dfn[x] == low[x]) {
int t; n++;
do {
t = S.top(); S.pop();
tot[n]++;
scc[t] = n;
} while(t != x);
}
}
 
namespace DP {
edge E[1000009], *pt = E, *head[maxn];
int dp[maxn], cnt[maxn];
bool vis[maxn];
void addedge(int u, int v) {
pt->to = v; pt->next = head[u]; head[u] = pt++;
}
void init() {
memset(dp, 0, sizeof dp);
memset(cnt, 0, sizeof cnt);
memset(vis, 0, sizeof vis);
}
void Dp(int x) {
if(vis[x]) return;
vis[x] = true;
for(edge* e = head[x]; e; e = e->next) {
Dp(e->to);
if(dp[e->to] > dp[x])
dp[x] = dp[e->to], cnt[x] = cnt[e->to];
else if(dp[e->to] == dp[x] && (cnt[x] += cnt[e->to]) >= MOD) 
cnt[x] -= MOD;
}
dp[x] += tot[x];
if(!cnt[x]) cnt[x] = 1;
}
void work() {
for(int i = 0; i <= n; i++) 
if(!vis[i]) Dp(i);
int ans = 0, ans0 = 0;
for(int i = 0; i <= n; i++)
if(dp[i] > ans) ans = dp[i], ans0 = cnt[i];
else if(ans == dp[i] && (ans0 += cnt[i]) >= MOD) ans0 -= MOD;
printf("%d\n%d\n", ans, ans0);
}
}
 
void AddEdge() {
for(int x = 0; x < N; x++)
for(edge* e = head[x]; e; e = e->next) 
if(scc[x] != scc[e->to] && bst.find(make_pair(scc[x], scc[e->to])) == bst.end()) {
DP::addedge(scc[x], scc[e->to]);
bst.insert(make_pair(scc[x], scc[e->to]));
}
}
 
void TARJAN() {
memset(dfn, 0, sizeof dfn);
memset(low, 0, sizeof low);
memset(scc, -1, sizeof scc);
memset(tot, 0, sizeof tot);
for(int i = 0; i < N; i++) if(!dfn[i]) tarjan(i);
}
 
void init() {
N = read();
int m = read();
MOD = read();
while(m--) {
int u = read() - 1, v = read() - 1;
addedge(u, v);
}
DP::init();
}
 
int main() {
init();
TARJAN();
DP::init();
AddEdge();
DP::work();
return 0;
}

-------------------------------------------------------------------------------------------

1093: [ZJOI2007]最大半连通子图

Time Limit: 30 Sec  Memory Limit: 162 MB
Submit: 2105  Solved: 841
[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

6 6 20070603
1 2
2 1
1 3
2 4
5 6
6 4

Sample Output

3
3

HINT

对于100%的数据, N ≤100000, M ≤1000000;对于100%的数据, X ≤10^8。

Source

BZOJ 1093: [ZJOI2007]最大半连通子图( tarjan + dp )的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. 【刷题】BZOJ 1093 [ZJOI2007]最大半连通子图

    Description 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意 两点u,v,存在一条u到v的有向路径或者从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. P2272 [ZJOI2007]最大半连通子图 tarjan+DP

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

  9. bzoj 1093: [ZJOI2007]最大半连通子图【tarjan+拓扑排序+dp】

    先tarjan缩成DAG,然后答案就变成了最长链,dp的同时计数即可 就是题面太唬人了,没反应过来 #include<iostream> #include<cstdio> #i ...

随机推荐

  1. Hibernate学习之映射关系

    一.Hibernate多对一关联映射:就是在“多”的一端加外键,指向“一”的一端. 比如多个学生对应一个班级,多个用户对应一个级别等等,都是多对一关系. 1.“多”端实体加入引用“一”端实体的变量及g ...

  2. 5.6.3.4 trim()方法

    ECMAScript 5 为所有字符串定义了trim()方法.这个方法会创建一个字符串的副本,删除前置以及后缀的所有空格,然后返回结果.例如: var stringValue = " hel ...

  3. ffmpeg 命令详解

    常用视频命令 //转码(并添加黑边) ffmpeg -ss start_time -i input.mp4 -t total_duration -vcodec copy/h264/... -acode ...

  4. python的内置函数bin()

    bin(x) 中文说明:将整数x转换为二进制字符串,如果x不为Python中int类型,x必须包含方法__index__()并且返回值为integer: 参数x:整数或者包含__index__()方法 ...

  5. mybatis+spring+c3p0+maven+ehcache

    项目截图 pom.xml如下 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http: ...

  6. Noip2008提高组总结

    Noip2008前三题是基础题,仔细一些都是可以AC的,第四题的证明很巧妙,但是看懂后代码其实很简单,感觉在这些大家都不屑去做的简单题中又学到了不少,四道题代码基本都是十几二十行就够了,渐渐感觉到,比 ...

  7. 过拟合/欠拟合&logistic回归等总结(Ng第二课)

    昨天学习完了Ng的第二课,总结如下: 过拟合:欠拟合: 参数学习算法:非参数学习算法 局部加权回归 KD tree 最小二乘 中心极限定律 感知器算法 sigmod函数 梯度下降/梯度上升 二元分类 ...

  8. JavaScript中的字符串

    JavaScript字符串是JavaScript最重要的部分,可能比任何其他的数据类型都更多的用到. 所有的JavaScript对象共享的方法之一就是toString(). 字符串对象叫做String ...

  9. Oracle存储包存储及案例

    Package左侧文件: create or replace package S02_ZFRZPT_YS_MID is procedure start_cal(strgranularity in va ...

  10. mac下面xcode+ndk7配置cocos2dx & box2d的跨ios和android平台的游戏教程

    这篇教程是介绍如何使用cocos2d-x和box2d来制作一个demo,且此demo能同时运行于ios和android平台.在继续阅读之前,建议您先阅读上一篇教程. 首先,按照上一篇教程,搭建好mac ...