博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ 1093 强连通缩点+DAG拓扑DP
阅读量:4566 次
发布时间:2019-06-08

本文共 3192 字,大约阅读时间需要 10 分钟。

缩点后在一个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
using namespace std;typedef long long ll;const int MAXN = 100005;const int MAXM = 1000005;int deep, colorsum = 0;int top;/*sta目前的大小*/int dfn[MAXN], color[MAXN], low[MAXN];int sta[MAXN];//存着当前所有可能能构成强连通分量的点bool visit[MAXN];//表示一个点目前是否在sta中int cnt[MAXN];//各个强连通分量中含点的数目int to[MAXM << 1], nxt[MAXM << 1], Head[MAXN], ed = 1;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] = 1; 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] = 0; while (sta[top] != x) { color[sta[top]] = colorsum; visit[sta[top--]] = 0; } top--; }}int X;int du[MAXN];vector
g[MAXN];map
, int> mp, mp2;queue
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 = 1; i <= m; i++) { scanf("%d %d", &u, &v); if (!mp2[make_pair(u, v)]) { addedge(u, v); mp2[make_pair(u, v)] = 1; } } for (int i = 1; i <= n; i++) { if (!dfn[i]) { tarjan(i); } cnt[color[i]]++; } for (u = 1; 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)] = 1; } } } } for (int i = 1; i <= colorsum; i++) { if (du[i] == 0) { que.push(i); ans[i] = 1; } } while (que.size()) { int x = que.front(); que.pop(); nowmaxn[x] += cnt[x]; for (int i = 0; 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] == 0) { que.push(v); } } } int anser = 0; int maxnn = 0; for (int i = 1; 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;}
View Code

 

转载于:https://www.cnblogs.com/Aragaki/p/11195465.html

你可能感兴趣的文章
c++ std::thread + lambda 实现计时器
查看>>
NSRunLoop个人理解
查看>>
BZOJ_1031_[JSOI2007]_字符串加密_(后缀数组)
查看>>
[osg]osg窗口显示和单屏幕显示
查看>>
前端技术在线文档地址链接
查看>>
077_打印各种时间格式
查看>>
[LeetCode] 101. Symmetric Tree_ Easy tag: BFS
查看>>
前端基础之html
查看>>
.Net基础之3——运算符
查看>>
scrapy管道MySQL简记
查看>>
使用 jQuery Deferred 和 Promise 创建响应式应用程序
查看>>
Bzoj1013--Jsoi2008球形空间产生器
查看>>
报文格式【定长报文】
查看>>
RDLC报表钻取空白页问题
查看>>
OS X升级到10.10之后使用pod出现问题的解决方法
查看>>
多路电梯调度的思想
查看>>
jQuery-对Select的操作
查看>>
过滤器、监听器、拦截器的区别
查看>>
为什么要进行需求分析?通常对软件系统有哪些需求?
查看>>
Oracle RAC环境下ASM磁盘组扩容
查看>>