[CF1137]Museums Tour
link
\(\text{Description:}\)
一个国家有 \(n\) 个城市,\(m\) 条有向道路组成。在这个国家一个星期有 \(d\) 天,每个城市有一个博物馆。
有个旅行团在城市 \(1\) 出发,当天是星期一。每天早上,如果这个城市的博物馆开了,那么可以去这个博物馆参观。每天晚上,旅行团可以选择沿一条出边前往下一个城市,或者结束旅行。一个城市可以经过多次。
请问旅行团最多能参观多少个博物馆。一个博物馆参观了多次,只计算一次。
\(1\le n, m\le 10^5,1\le d\le 50\)
\({\rm Solution:}\)
由于\({\rm d}\)只有\({\rm 50}\)天,所以考虑分层图,分成\({\rm 50}\)层,每个点只有在它开放的那个时间(那一层)有\({\rm 1}\)的权值,其余权值均为\({\rm 0}\),对于原图的一条边 \({\rm E(x, y)}\), 在分层图中 \({\rm E(x_i, y_{i+1}), (1\le i\le d-1)}\) 且 \({\rm E(x_d, y_1)}\)。
然后缩点成\({\rm DAG}\), \({\rm DP}\) 即可。
注意一个细节就是如果很多个点 \({\rm x_i}\) 在同一个强连通分量中,权值只加一次。
#include <vector>
#include <set>
#include <stack>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <assert.h>
#include <algorithm>
using namespace std;
#define LL long long
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define GO debug("GO\n")
#define rep(i, a, b) for (register int (i) = (a); (i) <= (b); ++ (i))
const int INF = 0x3f3f3f3f;
const char Enter = '\n';
inline int rint() {
register int x = 0, f = 1; register char c;
while (!isdigit(c = getchar())) if (c == '-') f = -1;
while (x = (x << 1) + (x << 3) + (c ^ 48), isdigit(c = getchar()));
return x * f;
}
struct Stream {
Stream operator>> (int &x)
{ x = rint(); return *this; }
Stream operator<< (int x)
{ printf("%d", x); return *this; }
Stream operator<< (char ch)
{ putchar(ch); return *this; }
} xin, xout;
template<typename T> inline void chkmin(T &a, T b) { a > b ? a = b : 0; }
template<typename T> inline void chkmax(T &a, T b) { a < b ? a = b : 0; }
const int N = 1e5 + 10;
struct Edge {
int v, nxt;
} E[N * 51];
int tot, head[N * 51];
vector<int> G[N * 51];
inline void add(int u, int v)
{ E[++tot] = (Edge){v, head[u]}; head[u] = tot; }
int n, m, d, val[N * 50], col[N * 50], dfn[N * 50], low[N * 50], have[N * 50];
stack<int> stk;
void tarjan(int u) {
dfn[u] = low[u] = ++dfn[0];
stk.push(u);
for (register int i = head[u]; i; i = E[i].nxt) {
int v = E[i].v;
if (!dfn[v]) tarjan(v), chkmin(low[u], low[v]);
else if (!col[v]) chkmin(low[u], dfn[v]);
}
if (dfn[u] == low[u]) {
col[0]++;
int v;
do {
v = stk.top(); stk.pop();
col[v] = col[0];
} while (v != u);
}
}
int dp[N * 50];
int DFS(int u) {
if (dp[u]) return dp[u];
for (int i = 0; i < G[u].size(); ++ i) {
int v = G[u][i];
chkmax(dp[u], DFS(v));
}
return dp[u] += val[u];
}
int main() {
xin >> n >> m >> d;// fast_read
int u, v;
rep(i, 1, m) {
xin >> u >> v;
rep(j, 1, d - 1) add(u + (j - 1) * n, v + j * n);
add(u + (d - 1) * n, v);
}
rep(i, 1, d * n) if (!dfn[i]) tarjan(i);
rep(i, 1, n * d) for (register int j = head[i]; j; j = E[j].nxt) if (col[E[j].v] != col[i])
G[col[i]].push_back(col[E[j].v]);
rep(i, 1, n) {
static char str[N]; scanf("%s", str + 1);
rep(j, 1, d) {
if (str[j] == '1' and have[col[i + (j - 1) * n]] != i)
have[col[i + (j - 1) * n]] = i, val[col[i + (j - 1) * n]]++;
}
}
xout << DFS(col[1]) << Enter;
return 0;
}
[CF1137]Museums Tour的更多相关文章
- CF1137 C. Museums Tour
CF1137 C. Museums Tour 一般来说的正常思路:看到有向图的第一思路都是缩点(但是要分析一波证明强联通分量中的个体可以拼凑成整体,一般都是边和点可以经过无数次然后贡献只算一次这种类型 ...
- CF 1138 E. Museums Tour
E. Museums Tour 链接 分析: 按时间建出分层图,每个点形如(u,t),表示u在在t个时刻的点,tarjan缩点.每个强连通分量中的点都能经过,然后DAG上dp. 代码: #includ ...
- CF1137C Museums Tour(Tarjan,强连通分量)
好题,神题. 题目链接:CF原网 洛谷 题目大意: 一个国家有 $n$ 个城市,$m$ 条有向道路组成.在这个国家一个星期有 $d$ 天,每个城市有一个博物馆. 有个旅行团在城市 $1$ 出发,当天是 ...
- 【Codeforces 1137C】Museums Tour
Codeforces 1137 C 题意:给一个有向图,一周有\(d\)天,每一个点在每一周的某些时刻会开放,现在可以在这个图上从\(1\)号点开始随意地走,问最多能走到多少个开放的点.一个点如果重复 ...
- CF1137C Museums Tour
思路 强连通分量的好题 对于每个博物馆,因为时间的限制条件,不好直接统计, 发现d很小,可以建出d层分层图,原图<u,v>的边变成<u,i>到<v,i+1>的边,& ...
- Codeforces 1137C Museums Tour (强连通分量, DP)
题意和思路看这篇博客就行了:https://www.cnblogs.com/cjyyb/p/10507937.html 有个问题需要注意:对于每个scc,只需要考虑进入这个scc的时间即可,其实和从哪 ...
- 【CF1137C】 Museums Tour 拆点+缩点
https://codeforc.es/contest/1137/problem/C # 题意 给你n个点,每个点有k天博物馆开放时间的安排表. 有m条单向道路,走过一条边需要一个晚上,经过后就是第二 ...
- CF1137C Museums Tour(tarjan+DP)
由于d很小,所以可以把每个点拆成d个点,然后对于边(x,y),连边时连接((x,i),(y,i+1))及((x,d),(y,1)).然后可以对这样连的边跑一遍tarjan缩点.然后直接暴力DP即可.不 ...
- codeforces选做
收录了最近本人完成的一部分codeforces习题,不定期更新 codeforces 1132E Knapsack 注意到如果只使用某一种物品,那么这八种物品可以达到的最小相同重量为\(840\) 故 ...
随机推荐
- Git IDEA Move or commit them before merge
提交代码遇到这个问题. Move or commit them before merge 百度了一下都是在Gitbash 中敲命令. 在团队协作中 你总不能去敲命令吧 后来在组长的怂恿下,我删除了一个 ...
- Web | 一小时看懂前端基本语法
自从H5出来之后,web前端的势头好像就有点燎原之势.国内互联网的发展就是这样,像之前的移动App(iOS.Android),简直是火的一塌糊涂.所以不管是培训机构也好,自学成才也好,都是一种途径,能 ...
- VUE 跳转另一页面返回之前页面刷新,但数据依然存在
在第一个页面填写数据后存入本地缓存: 再次跳转回来时判断是否填入数据,如果有数据,将缓存数据填写上.
- NFS服务的搭建
NFS服务的作用:提供网络文件系统给客户机 nfs服务器的安装配置和使用: 1.将已经制作好的文件系统rootfs_fs210_audio.tgz 拷贝到 /opt,并解压(这里的/opt目录是通过s ...
- Java实例 Part4:数组及其常用操作
目录 Part4:数组及其常用操作 Example01:将二维数组的行列交换 Example02:使用选择排序法对数组进行排序 Example03:使用冒泡排序法对数组进行排序 Example04:使 ...
- IC设计笔试面试小问题总结(随时更新)-IC设计笔记(三)
都是一些细节性问题,放在一起记忆,一问一答的形式,有任何问题欢迎文章上方微博讨论,多思多想. 1.What makes the difference between Run time and CPU ...
- QPushButton槽函数触发两次的问题
以前经常使用qt creator界面管理直接跳转到槽函数没发现这个问题,今天手动写了个槽函数发现按键会触发两次.根据网上的说法是按键会自动连接一个槽函数,如果我们手动添加的槽函数命名规则符合槽函数的命 ...
- 自己写的一些Excel及WordVBA函数[原创]
1.将Excel当前工作表另存至桌面 Excel中有时一个工作簿中工作表特别多,需要快速单独存取其中一个,可用以下代码快速存至桌面 Sub 另存工作表到桌面() Dim sh As Worksheet ...
- SVN-Tips
一些实际使用中遇到与学习的SVN的TIPS 1.如何从SVN检出maven项目: 1.从svn导入“作为工作空间中的项目检出”--->Finish 2.如“1”操作后,会自动的在MyEclips ...
- 20155308 2016-2017-2 《Java程序设计》实验3
20155308 2016-2017-2 <Java程序设计>实验3 实验内容 XP基础 XP核心实践 相关工具 实验步骤 (一)敏捷开发与XP 敏捷开发是一种以人为核心.迭代.循序渐进的 ...