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. C++的常量折叠(一)

    前言 前几天女票问了我一个阿里的面试题,是有关C++语言的const常量的,其实她一提出来我就知道考察的点了:肯定是const常量的内存不是分配在read-only的存储区的,const常量的内存分配 ...

  2. Oracle "Job定时"

    今天需要做个定时器,定时到别的库导入数据用到了Job,第一次使用记录下来,如果有第一次操作的可以借鉴一下 1.首先,使用Toad新建job,进入配置页面

  3. 05-C语言运算符

    目录: 一.进制转换 二.常量 三.sizeof 四.运算符 五.赋值运算符 六.自增减运算符 七.关系运算符 八.逻辑运算符 九.取址寻址运算符 回到顶部 一.进制转换 1 进制转换是人们利用符号来 ...

  4. Hbuilder 常用快捷键汇总

    朋友推荐用Hbuilder编辑器,看了下Hbuilder官网和那视频,感觉牛逼哄哄的, 自己也就体验了一下,打开Hbuilder的快捷键列表,每个快捷键都体验了一下,以下展示出来的,每一个都是精华,每 ...

  5. 将MFC Grid control封装为DLL的做法及其在DLL中的使用方法

    MFCGrid control是一款非常优秀的网格控件,支持非常丰富的界面元素,如下图: 因而在数据库程序及报表程序应用较为广泛,其源码可以在下面下载到: MFC Grid control2.27源码 ...

  6. poj 2153 Rank List(查找,Map)

    题目链接:http://poj.org/problem?id=2153 思路分析: 判断Li Ming的成绩排名,需要在所有的数据章查找成绩比其高的人的数目,为查找问题. 查找问题可以使用Hash表, ...

  7. Eclipse快捷键 今天又学会了几个不常用的 收藏了

    1.Ctrl+e           打开所有已经打开的文件列表,当你使用Eclipse打开了N多文件的时候,需要找到一个你之前打开过                       的文件,是不是就很费 ...

  8. 【转】Configuring VM Acceleration on Linux

    Configuring VM Acceleration on Linux Linux-based systems support virtual machine acceleration throug ...

  9. SQL Server验证的两种方式

    1.Windows身份验证:本机连接或者受信的局域网连接(一般在忘记管理员密码或者做系统配置的情况下使用). 2.SQLServer验证:使用用户名.密码验证(推荐使用). 启用方法:以Windows ...

  10. Jenkins持续集成相关文章整理

    构建iOS持续集成平台(一)——自动化构建和依赖管理 构建iOS持续集成平台(二)——测试框架 构建iOS持续集成平台(三)——CI服务器与自动化部署 使用Jenkins搭建iOS开发的CI服务器 一 ...