[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\) 故 ...
随机推荐
- 编译nginx错误:make[1]: *** [/pcre//Makefile] Error 127
--with-pcre=DIR 是设置源码目录,而不是编译安装后的目录.
- Oracle数据库sql语句
1.创建用户.赋权限.删除用户 create user test identified by test default test users temporary tablespace temp; gr ...
- iOS之面试题:阿里-P6一面-参考思路
阿里-p6-一面 1.介绍下内存的几大区域? 2.你是如何组件化解耦的? 3.runtime如何通过selector找到对应的IMP地址 4.runloop内部实现逻辑? 5.你理解的多线程? 6. ...
- windows10 通过命令行来查看wifi密码
c:\Windows\System32>netsh netsh>wlan show profile 接口 WLAN 上的配置文件: 组策略配置文件(只读) ---------------- ...
- jdbc之Statement和Preparement
Jdbc DML 操作 Statement:静态SQL操作 每次操作都会将sql语句提交到数据库执行一次,性能比较低 // 1.加载驱动程序 Class.forName(driverName); // ...
- 02.centos7上搭建hadoop集群
接上一篇 https://www.cnblogs.com/yjm0330/p/10069224.html 一.准备工作:无密登陆 1.编辑/etc/hosts文件,分别增加 192.168.2.24 ...
- hadoop排序 -- 全排序
目录 一.关于Reducer全排序 1.1. 什么叫全排序 1.2. 分区的标准是什么 二.全排序的三种方式 2.1. 一个Reducer 2.2. 自定义分区函数 2.3. 采样 一.关于Reduc ...
- 【树形DP】MZOJ_1063_士兵守卫
本题也是这三天来在下写的几篇树形DP之一,但是不知道为什么洛谷上面老是unknown error,...直接去了UVa,说我编译错误...我在想是不是头文件的原因,于是被逼无奈,交了一道c89的代码. ...
- c语言实验报告(四) 从键盘输入字符串a和字符串b,并在a串中的最小元素(不含结束符)后面插入字符串b.
a串中最小元素后的字符被舍弃了. #include<stdio.h>#include<string.h>void main(){ int i,min=0; char a[2 ...
- Go Web 使用工具
前端工具: sublime text3 下载:https://www.sublimetext.com/3 中文版设置:https://jingyan.baidu.com/article/9c69d48 ...