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. jackson的简单实用实例(json)

    一个json格式的字符串比如: {"status":10001,"code":"HDkGzI","pubkey":&qu ...

  2. SpringMVC之访问静态文件

    我们在进行springMVC开发时,必定会在jsp页面引入js文件.img文件和css文件.大多数人会将这些分类存放在WebRoot文件下新建的文件夹下面.同时,会在web.xml文件中配置拦截所有请 ...

  3. 面试题:在O(1)时间删除链表结点

    题目:给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点. 链表结点与函数的定义如下: struct ListNode { int m_nValue; ListNode* m_p ...

  4. 如何使用robots不让百度和google收录

    如何使用robots不让百度和google收录   有没有想过,如果我们某个站点不让百度和google收录,那怎么办? 搜索引擎已经和我们达成一个约定,如果我们按约定那样做了,它们就不要收录. 这个写 ...

  5. HDU 3625 Examining the Rooms

    题目大意:有n个房间,n!个钥匙,在房间中,最多可以破k扇门,然后得到其中的钥匙,去开其它的门,但是第一扇门不可以破开,求可以打开所有门的概率. 题解:首先,建立这样的一个模型,题目相当于给出一个图, ...

  6. HA for openstack

    mysql ha instance ha openstack博客:http://blog.csdn.net/tantexian/article/list/2 使用eclipse远程调试openstac ...

  7. struct 如何存储指针类型的值

    通过 __unsafe_unretained标示符标示指针类型的值,否则xcode会报以下错误(前提,你使用的是ARC模式): ARC forbids Objective-C objects in s ...

  8. C# Best Practices - Building Good Classes

    Building a Class The last four refer as members Signature Accessiblity modifier (Default:internal) c ...

  9. centos7/redhat7 将网卡名字改成eth样式的方法

    方法/步骤    1. 编辑 /etc/sysconfig/grub 找到“GRUB_CMDLINE_LINUX”这一行 

  10. Python网络编程——设备名和IPv4地址

    1.快速查看主机名和对应的IP地址小程序 import socket def print_machine_info(): # 定义print_machine_info()类 host_name = s ...