BZOJ 1093 强连通缩点+DAG拓扑DP
缩点后在一个DAG上求最长点权链 和方案数
注意转移条件和转移状态
if (nowmaxn[x] > nowmaxn[v]) {
ans[v] = ans[x];
nowmaxn[v] = nowmaxn[x];
} else if (nowmaxn[x] == nowmaxn[v]) {
ans[v] = (ans[v] + ans[x]) % X;
}
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = ;
const int MAXM = ;
int deep, colorsum = ;
int top;/*sta目前的大小*/
int dfn[MAXN], color[MAXN], low[MAXN];
int sta[MAXN];//存着当前所有可能能构成强连通分量的点
bool visit[MAXN];//表示一个点目前是否在sta中
int cnt[MAXN];//各个强连通分量中含点的数目
int to[MAXM << ], nxt[MAXM << ], Head[MAXN], ed = ;
inline void addedge(int u, int v)
{
to[++ed] = v;
nxt[ed] = Head[u];
Head[u] = ed;
}
void tarjan(int x)
{
dfn[x] = ++deep;
low[x] = deep;
visit[x] = ;
sta[++top] = x;
for (int i = Head[x]; i; i = nxt[i]) {
int v = to[i];
if (!dfn[v]) {
tarjan(v);
low[x] = min(low[x], low[v]);
} else {
if (visit[v]) {
low[x] = min(low[x], low[v]);
}
}
}
if (dfn[x] == low[x]) {
color[x] = ++colorsum;
visit[x] = ;
while (sta[top] != x) {
color[sta[top]] = colorsum;
visit[sta[top--]] = ;
}
top--;
}
}
int X;
int du[MAXN];
vector<int> g[MAXN];
map<pair<int, int>, int> mp, mp2;
queue<int> que;
int ans[MAXN];
int nowmaxn[MAXN];
int main()
{
int n, m;
int u, v;
scanf("%d %d %d", &n, &m, &X);
for (int i = ; i <= m; i++) {
scanf("%d %d", &u, &v);
if (!mp2[make_pair(u, v)]) {
addedge(u, v);
mp2[make_pair(u, v)] = ;
}
}
for (int i = ; i <= n; i++) {
if (!dfn[i]) {
tarjan(i);
}
cnt[color[i]]++;
}
for (u = ; u <= n; u++) {
int x = color[u];
for (int i = Head[u]; i; i = nxt[i]) {
v = to[i];
int y = color[v];
if (x != y) {
if (!mp[make_pair(x, y)]) {
g[x].push_back(y);
du[y]++;
mp[make_pair(x, y)] = ;
}
}
}
}
for (int i = ; i <= colorsum; i++) {
if (du[i] == ) {
que.push(i);
ans[i] = ;
}
}
while (que.size()) {
int x = que.front();
que.pop();
nowmaxn[x] += cnt[x];
for (int i = ; i < g[x].size(); i++) {
v = g[x][i];
if (nowmaxn[x] > nowmaxn[v]) {
ans[v] = ans[x];
nowmaxn[v] = nowmaxn[x];
} else if (nowmaxn[x] == nowmaxn[v]) {
ans[v] = (ans[v] + ans[x]) % X;
}
du[v]--;
if (du[v] == ) {
que.push(v);
}
}
}
int anser = ;
int maxnn = ;
for (int i = ; i <= colorsum; i++) {
if (nowmaxn[i] > maxnn) {
anser = ans[i];
maxnn = nowmaxn[i];
} else if (nowmaxn[i] == maxnn) {
anser = (anser + ans[i]) % X;
}
}
cout << maxnn << endl;
cout << anser << endl; }
BZOJ 1093 强连通缩点+DAG拓扑DP的更多相关文章
- UVA 11324 The Largest Clique(强连通分量+缩点DAG的DP)
题意:给定一个有向图,求出一个最大的结点集,这个节点集中的随意两个点之间至少一个能到达还有一个点. 思路:假设一个点在这个节点集中,那么它所在的强连通分量中的点一定所有在这个节点集中,反之亦然, 求出 ...
- BZOJ 5450 轰炸 (强连通缩点+DAG最长路)
<题目链接> 题目大意: 有n座城市,城市之间建立了m条有向的地下通道.你需要发起若干轮轰炸,每轮可以轰炸任意多个城市.但每次轰炸的城市中,不能存在两个不同的城市i,j满足可以通过地道从城 ...
- bzoj1179: [Apio2009]Atm scc缩点+dag上dp
先把强连通缩点,然后变成了dag,dp求终点是酒吧的最长路即可, /************************************************************** Pro ...
- 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 ...
- Tarjan缩点+DAG图dp
题目背景 缩点+DP 题目描述 给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大.你只需要求出这个权值和. 允许多次经过一条边或者一个点,但是,重复经过的点,权值只 ...
- UVA - 11324 The Largest Clique 强连通缩点+记忆化dp
题目要求一个最大的弱联通图. 首先对于原图进行强连通缩点,得到新图,这个新图呈链状,类似树结构. 对新图进行记忆化dp,求一条权值最长的链,每一个点的权值就是当前强连通分量点的个数. /* Tarja ...
- BZOJ5017 [Snoi2017]炸弹[线段树优化建边+scc缩点+DAG上DP/线性递推]
方法一: 朴素思路:果断建图,每次二分出一个区间然后要向这个区间每个点连有向边,然后一个环的话是可以互相引爆的,缩点之后就是一个DAG,求每个点出发有多少可达点. 然后注意两个问题: 上述建边显然$n ...
- POJ 1236 学校传数据 强连通+缩点+DAG
题意描述: 网络中有一些学校,每个学校可以分发软件给其他学校.可以向哪个分发取决于他们各自维护的一个清单. 两个问题 1:至少要copy多少份新软件给那些学校, 才能使得每个学校都能得到. 2:要在所 ...
- [模板][Luogu3387] 缩点 - Tarjan, 拓扑+DP
Description 给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大.你只需要求出这个权值和. 允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次 ...
随机推荐
- C++通过Swig跨线程回调Python代码
C++ 定义 Callback 类. PyThreadStateLock 保证垮线程调用成功: #include <Python/Python.h> class Callback { pu ...
- 洛谷 题解 P2119【魔法阵】
很好的一道数学推导题 45分做法 \(O(N^4)\) 暴力枚举四个材料 55分做法 从第一个约束条件可得到所有可行答案都是单调递增的,所以可以排序一遍,减少枚举量,可以拿到55分 100分做法 首先 ...
- 后台返回数据为map集合,前端js处理方法
当后台返回的数据不是json而是map集合的时候,前端js中处理就将其看作是一个数组,例如后台返回的代码入下: Map<String, String> result = new HashM ...
- Django-djangorestframework-响应模块
响应模块 一般都用 Response 对象来做返回(最后一定是打包成符合 HTTP 协议的数据格式来传输,Response 类做了一系列处理,所以这里我们只需要关注下它的那些参数即可) 响应类构造器 ...
- 输入一个正整数n,输出所有和为n的连续正整数序列
public static void main(String[] args) { Scanner sc = new Scanner(System.in); while (true) { System. ...
- javascript 的惯性运动
移动端的惯性运动,最早来自 ios 的专利.用于手指滑动,离开屏幕之后,屏幕内容继续滚动.更有动态感. 这里,以 pc 端,鼠标横向(沿x轴) 拖拽的,惯性计算.移动端同理 具体代码如下: <! ...
- 怎样获取xhr的当前状态
一个XMLHttpRequets实例从创建到发起请求再到获取数据, 期间会有一些中间状态, 这些状态是必要的, 我们可以通过判断这些状态值来进行不同的动作. xhr中获取请求状态的属性是: xhr.r ...
- Unity异步加载场景
在游戏中,经常可以看到从一个关卡跳到另一个关卡时,有一个显眼的进度条,研究了下,其时也很简单: public void LoadAScene() { StartCoroutine(LoadSce ...
- AngularJS-02 数据绑定和表达式
AngularJS----数据绑定和表达式 1.表达式是AngularJS模板引擎的重要内容,也是视图View的必要组成部分,用来将模型动态转换为可视DOM元素或者其内容. 表达式的形式: 1)常量: ...
- MediaAPIController
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.D ...