https://codeforc.es/contest/1137/problem/C

# 题意

给你n个点,每个点有k天博物馆开放时间的安排表。

有m条单向道路,走过一条边需要一个晚上,经过后就是第二天的意思。

问在无穷大的时间里,可以参观多少不同的博物馆。

# 思路

我们把每个点都拆出k个点,有单向边相连就从(u,i) -> (v, (i+1)%k)。

缩点跑出DAG,然后DP出最多的博物馆参观数。

这里就要考虑直接DP是否能行。假设有一条(u,i) -> (u, j)的边,由于没有自环且是单向边,所以一定可以通过循环,可以从(u,j)再走到(u,i),所以这两个点会缩在一起。

由于这种做法缩点时递归很深,我是通过inline优化的,开O(3)好像也可以。

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
 
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
 
template<class T> void _R(T &x) { cin >> x; }
void _R(int &x) { scanf("%d", &x); }
void _R(ll &x) { scanf("%lld", &x); }
void _R(double &x) { scanf("%lf", &x); }
void _R(char &x) { scanf(" %c", &x); }
void _R(char *x) { scanf("%s", x); }
void R() {}
template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); }
 
 
template<typename T>
inline T read(T&x){
x=;int f=;char ch=getchar();
while (ch<''||ch>'') f|=(ch=='-'),ch=getchar();
while (ch>=''&&ch<='') x=x*+ch-'',ch=getchar();
return x=f?-x:x;
}
 
const int inf = 0x3f3f3f3f;
 
const int mod = 1e9+;
 
/**********showtime************/
const int maxn = ;
 
// vector<int>mp[maxn];
 
int n,m,k;
int getid(int x, int i) {
return (x - ) * k + i + ;
}
 
struct E{
int u,v;
int nxt;
}edge[maxn];
 
int gtot = , head[maxn];
 
void addedge(int u, int v) {
edge[gtot].u = u;
edge[gtot].v = v;
edge[gtot].nxt = head[u];
head[u] = gtot++;
}
 
set <int> dpmp[maxn];
 
char str[];
int dp[maxn],a[maxn];
int belong[maxn], dfn[maxn] , low[maxn];
 
bool vis[maxn];
bool flag[maxn];
// int used[maxn];
 
int tim, scc_cnt;
 
//stack<int>st;
queue<int>que;
int st[];
int top = ;
inline void dfs(int u) {
dfn[u] = low[u] = ++tim;
 
// st.push(u);
st[++top] = u;
for(int i=head[u]; ~i; i=edge[i].nxt){
int v = edge[i].v;
if(!dfn[v]) dfs(v);
if(!belong[v]) low[u] = min(low[u], low[v]);
}
 
if(dfn[u] == low[u]) {
scc_cnt++;
int now;
while(true) {
now = st[top]; top--;
belong[now] = scc_cnt;
if(flag[now]) {
int id = (now - ) / k + ;
if(vis[id] == ) {
que.push(id);
vis[id] = ;
a[scc_cnt]++;
}
}
if(now == u) break;
}
while(!que.empty()) {
int u = que.front(); que.pop();
vis[u] = ;
}
}
}
 
int ans = ; void cal(int s) {
queue<int>que;
dp[s] = a[s];
que.push(s);
ans = max(ans, a[s]);
 
while(!que.empty()) {
int u = que.front(); que.pop();
vis[u] = ;
for(int v : dpmp[u]) {
dp[v] = max(dp[v], dp[u] + a[v]);
ans = max(ans, dp[v]);
if(vis[v] == ) {
vis[v] = ;
que.push(v);
}
}
}
}
int main(){
memset(head, -, sizeof(head));
R(n, m, k);
for(int i=; i<=m; i++) {
int u,v;
scanf("%d%d", &u, &v);
for(int j=; j<k; j++) {
addedge(getid(u, j), getid(v, (j+)%k));
}
}
 
for(int i=; i<=n; i++) {
scanf("%s", str);
for(int j=; j<k; j++) {
flag[getid(i, j)] = (str[j] == '');
}
}
 
for(int i=; i<=n; i++){
for(int j=; j<k; j++)
if(!dfn[getid(i, j)]) dfs(getid(i, j));
}
 
for(int i=; i<gtot; i++){
int u = edge[i].u, v = edge[i].v;
if(belong[u] == belong[v]) continue;
dpmp[belong[u]].insert(belong[v]);
}
 
cal(belong[getid(, )]);
 
printf("%d\n", ans);
return ;
}

最新文章

  1. bzoj4691: Let There Be Light
  2. 天津政府应急系统之GIS一张图(arcgis api for flex)讲解(二)鹰眼模块
  3. SQL Server 常用日期查询语句
  4. 【python】一个简单的贪婪爬虫
  5. 对memcpy函数的改进
  6. 【Qt】Qt之进程间通信(IPC)【转】
  7. while死循环问题-输入字符就会死循环
  8. [Hapi.js] Request Validation with Joi
  9. ROOT android 原则。 基于(zergRush)
  10. 2_http协议详解
  11. mysql常用基础操作语法(八)~~多表查询合并结果和内连接查询【命令行模式】
  12. for循环中按条件删除数据元素
  13. Linux服务器重启后MySQL启动失败
  14. apply、call、bind的区别
  15. python入门第一篇
  16. learning ddr DLL-off mode
  17. elk之[logstash-input-file]插件使用详解
  18. ISCSI工作流程target和initiator
  19. UVA 1508 - Equipment 状态压缩 枚举子集 dfs
  20. Java编程的逻辑 (33) - Joda-Time

热门文章

  1. 极简代码神器:Lombok使用教程
  2. 终极版Servlet——我只能提示您路过别错过
  3. 【iOS】Ineligible Devices || “无法下载应用程序”
  4. springboot-权限控制shiro(二)
  5. plotly之set_credentials_file问题
  6. java 动手动脑7
  7. bootstrape select使用小结
  8. Java 操作Word书签(一):添加、删除、读取书签
  9. 自己动手实现MQTT协议
  10. Javasrcipt中从一个url或者从一个字符串中获取参数值得方法