CF1137 C. Museums Tour

一般来说的正常思路:看到有向图的第一思路都是缩点(但是要分析一波证明强联通分量中的个体可以拼凑成整体,一般都是边和点可以经过无数次然后贡献只算一次这种类型)\(DAG\)上面DP.

这道题第一眼看上去比较麻烦,因为这个时间限制比较恶心的样子.

我们考虑拆点,将一个点拆成\(d\)个,\((i,j)\)表示第\(i\)个点在第\(j\)天的联通情况

这样的话,我们在缩点的时候,就统计一下每一个强联通分量内有多少点在其对应的博物馆的开放时间内(注意去重)

这样的话,我们貌似就得到了每个强联通分量的点权

剩下的貌似就是一个\(DAG\)上的最长链问题了.

但是我们好像没有考虑一个点在两个或多个强联通分量都有贡献的情况

很幸运这是不需要考虑的.因为不可能出现上述情况

为什么?

我们说假设存在这样一次路径,满足\((i,x) ->(i,y)\)即从\(i\)点的第\(x\)天能够到达第\(i\)个点的第\(y\)天,我们设\(\Delta d = y - x\)(默认\(y\)大于\(x\))

那么一定存在\((i,0)->(i,d - 1)\)

以此类催,我们发现从\(y\)也可以到达\(x\),那么他们必在同一强联通分量内

然后就结束了

我栈用了存边数组的变量\(tot\)导致疯狂RE

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 3;
const int M = 61;
struct edge{
int to;
int nxt;
}e[N * M];
vector <int> G[N * M];
int val[N * M],head[N * M];
char s[N][M];
int tot;
int cnt,n,m,d,idx,top;
bool insta[N * M];
int sta[N * M];
int dfn[N * M],belong[N * M],low[N * M];
int f[N * M];
//int can[N];
bool flag[N * M];
int out[N * M];
//inline char nc(){
// #define SIZE 100000
// static char buf[SIZE],*p1 = buf+SIZE,*pend = buf+SIZE;
// if(p1 == pend){
// p1 = buf;pend = buf+fread(buf,1,SIZE,stdin);
// if(p1 == pend) return -1;
// }
// return *p1++;
// #undef SIZE
//}
inline void read(int &x){
x = 0;int flag = 0;
char ch = getchar();
while(!isdigit(ch)){
if(ch == '-') flag = 1;
ch = getchar();
}
while(isdigit(ch)){
x = (x<<1) + (x<<3) + (ch^'0');
ch = getchar();
}
if(flag) x = -x;
}
inline void add(int x,int y){
e[++tot].to = y;
e[tot].nxt = head[x];
head[x] = tot;
}
inline void tarjan(int x){
// cout << x << endl;
dfn[x] = low[x] = ++idx;
sta[++top] = x;
insta[x] = 1;
for(int i = head[x];i;i = e[i].nxt){
int y = e[i].to;
if(!dfn[y]){
tarjan(y);
low[x] = min(low[x],low[y]);
}
else if(insta[y]) low[x] = min(low[x],dfn[y]);
}
if(dfn[x] == low[x]){
int k;cnt++;
int fo = top;
do{
//tot = -1;
k = sta[top--];
insta[k] = 0;
belong[k] = cnt;
if(s[k / d][k % d] == '1' && flag[k / d] == 0) {val[cnt]++;flag[k / d] = 1;}
// if(k % d == 0) can[cnt] = 1;
}while(k != x);
for(int i = fo;i != top;--i) flag[sta[i] / d] = 0;
}
}
inline int tops(){
queue <int> q;
// q.push(belong[0]);
// cout <<in[belong[0]] << endl;
for(int i = 1;i <= cnt;++i) f[i] = val[i];
for(int i = 1;i <= cnt;++i) if(!out[i]) f[i] = val[i],q.push(i);
while(!q.empty()){
int k = q.front();q.pop();
for(int i = 0;i < (int)G[k].size();++i){
int y = G[k][i];
f[y] = max(f[y],f[k] + val[y]);
out[y]--;
if(!out[y]) q.push(y);
}
}
// for(int i = 1;i <= cnt;++i) cout << f[i] << ' ';cout << endl;
return f[belong[0]];
}
int main(){
// printf("%d\n",sizeof(e) / 1024 / 1024);
read(n),read(m),read(d);
for(int i = 1;i <= m;++i){
int x,y,z;
read(x);read(y);x--,y--;
for(int j = 0;j < d;++j)
add(x * d + j,y * d + ((j + 1) % d));
}
for(int i = 0;i < n;++i) scanf("%s",s[i]);
if(n == 1 && m == 0){
cout << s[0][0];
return 0;
}
// if(n == 99998){cout << "GG";return 0;}
for(int i = 0;i < n * d;++i)
if(!dfn[i]) tarjan(i);
//for(int i = 0;i < n * d;++i) printf("%d ",belong[i]);puts("");
// cout << cnt << endl;
// for(int i = 1;i <= cnt;++i) cout << val[i] << " ";cout << endl;
for(int i = 0;i < n * d;++i){
for(int j = head[i];j;j = e[j].nxt){
int y = e[j].to;
if(belong[i] != belong[y]) G[belong[y]].push_back(belong[i]),out[belong[i]]++;//printf("%d %d\n",belong[i],belong[y]);
}
}
//cout << cnt << endl;
// for(int i = 1;i <= cnt;++i){
// printf("now:%d: ",i);
// for(int j = 0;j < G[i].size();++j){
// printf("%d ",G[i][j]);
// }
// puts("");
// }
printf("%d\n",tops());
return 0;
}

CF1137 C. Museums Tour的更多相关文章

  1. CF 1138 E. Museums Tour

    E. Museums Tour 链接 分析: 按时间建出分层图,每个点形如(u,t),表示u在在t个时刻的点,tarjan缩点.每个强连通分量中的点都能经过,然后DAG上dp. 代码: #includ ...

  2. [CF1137]Museums Tour

    link \(\text{Description:}\) 一个国家有 \(n\) 个城市,\(m\) 条有向道路组成.在这个国家一个星期有 \(d\) 天,每个城市有一个博物馆. 有个旅行团在城市 \ ...

  3. CF1137C Museums Tour(Tarjan,强连通分量)

    好题,神题. 题目链接:CF原网 洛谷 题目大意: 一个国家有 $n$ 个城市,$m$ 条有向道路组成.在这个国家一个星期有 $d$ 天,每个城市有一个博物馆. 有个旅行团在城市 $1$ 出发,当天是 ...

  4. 【Codeforces 1137C】Museums Tour

    Codeforces 1137 C 题意:给一个有向图,一周有\(d\)天,每一个点在每一周的某些时刻会开放,现在可以在这个图上从\(1\)号点开始随意地走,问最多能走到多少个开放的点.一个点如果重复 ...

  5. CF1137C Museums Tour

    思路 强连通分量的好题 对于每个博物馆,因为时间的限制条件,不好直接统计, 发现d很小,可以建出d层分层图,原图<u,v>的边变成<u,i>到<v,i+1>的边,& ...

  6. Codeforces 1137C Museums Tour (强连通分量, DP)

    题意和思路看这篇博客就行了:https://www.cnblogs.com/cjyyb/p/10507937.html 有个问题需要注意:对于每个scc,只需要考虑进入这个scc的时间即可,其实和从哪 ...

  7. 【CF1137C】 Museums Tour 拆点+缩点

    https://codeforc.es/contest/1137/problem/C # 题意 给你n个点,每个点有k天博物馆开放时间的安排表. 有m条单向道路,走过一条边需要一个晚上,经过后就是第二 ...

  8. CF1137C Museums Tour(tarjan+DP)

    由于d很小,所以可以把每个点拆成d个点,然后对于边(x,y),连边时连接((x,i),(y,i+1))及((x,d),(y,1)).然后可以对这样连的边跑一遍tarjan缩点.然后直接暴力DP即可.不 ...

  9. codeforces选做

    收录了最近本人完成的一部分codeforces习题,不定期更新 codeforces 1132E Knapsack 注意到如果只使用某一种物品,那么这八种物品可以达到的最小相同重量为\(840\) 故 ...

随机推荐

  1. Linux进程管理(三、 线程)

    // ---- refer glibc, pthread_create.c ----// int __pthread_create_2_0 (newthread, attr, start_routin ...

  2. 【JZOJ4855】【NOIP2016提高A组集训第6场11.3】荷花池塘

    题目描述 于大夫建造了一个美丽的池塘,用来让自己愉快的玩耍.这个长方形的池子被分割成了M 行 和N 列的正方形格子.池塘中有些地方是可以跳上的荷叶,有些地方是不能放置荷叶也不 能跳上的岩石,其他地方是 ...

  3. iOS 万能跳转界面方法 (runtime实用篇一)

    http://www.cocoachina.com/ios/20150824/13104.html 作者:汉斯哈哈哈 授权本站转载. 在开发项目中,会有这样变态的需求: 推送:根据服务端推送过来的数据 ...

  4. 2019-9-23-dotnet-判断特定进程存在方法

    title author date CreateTime categories dotnet 判断特定进程存在方法 lindexi 2019-09-23 16:20:42 +0800 2019-09- ...

  5. Java注解初步了解 2016-07-24 22:20 240人阅读 评论(21) 收藏

    Java注解又称Java标注,是Java语言5.0版本开始支持加入源代码的特殊语法元数据. Java语言中的类.方法.变量.参数和包等都可以被标注.Java标注和Javadoc不同,标注有自反性.在编 ...

  6. 洛谷4137 mex题解 主席树

    题目链接 虽然可以用离线算法水过去,但如果强制在线不就gg了. 所以要用在线算法. 首先,所有大于n的数其实可以忽略,因为mex的值不可能大于n 我们来设想一下,假设已经求出了从0到n中所有数在原序列 ...

  7. 2019-2-11-WPF-获取应用的所有窗口

    title author date CreateTime categories WPF 获取应用的所有窗口 lindexi 2019-02-11 08:55:31 +0800 2019-02-11 0 ...

  8. ubuntu14.04 dnsmasq搭建本地名字服务器

    1 修改dnsmasq配置文件/etc/dnsmasq.conf 在/etc/dnsmasq.conf文件底部增加 #++++++++++++++++++++++++++++++++++++++++ ...

  9. laravel asset()函数

    asset() 使用当前请求的scheme(HTTP或HTTPS)为前端资源生成一个URL: $url = asset('img/photo.jpg'); laravel自带了laravel-mix, ...

  10. 在字符串中查找id值MySQL

    PHPmyadmin中sql语句 SELECT * FROM `hz_article_type` WHERE FIND_IN_SET( 5, items_id ) LIMIT 0 , 30 结果: S ...