题目链接  Smile House

题意  给定一个$n$个点的有向图,求一个点数最少的环,使得边权之和$>0$,这里的环可以重复经过点和边。

    满足  $n <= 300$

首先答案肯定是单调的,但是观察发现只有当我们给所有的点加一个自环的时候才满足这个性质。

考虑$DP$。设$f[i][j][k]$为长度为$i$,从$j$走到$k$能经过的最大边权和。

那么$f[i][j][k] = min(f[i-1][j][l] + g[l][k])$,这样的预处理是$O(n^{4})$的,$TLE$。

考虑$f[i][j][k]$为长度为$2^{i}$,从$j$走到$k$能经过的最大边权和。

那么$f[i][j][k] = min(f[i-1][j][l] + f[i - 1][l][k])$, 这样的预处理是$O(n^{3}logn)$的。

现在考虑二分答案。把当前验证的答案$u$拆成不同的几个$2$的幂次(最多$logn$个)。

令$u = 2^{a_{1}} + 2^{a_{2}} + 2^{a_{3}} + ... + 2 ^ {a_{m}}$

设$c[i][j]$为若只考虑长度为$2^{a_{1}}$, $2^{a_{2}}$, ...,  $2^{a_{m}}$的边,从$i$走到$j$经过的路径权值和的最大值。

那么又是一波$O(n^{3}logn)$的转移。

若最后存在$c[i][i] > 0$,则$u$可行。

加上二分答案的那个$log$,

时间复杂度$O(n^{3}log^{2}n)$

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i)
#define MP make_pair
#define fi first
#define se second typedef long long LL; const int inf = 1e9; const int N = 306; int n, m;
int f[10][N][N], c[2][N][N];
int l, r; bool check(int u){
int x = 0;
rep(i, 1, n) rep(j, 1, n) c[0][i][j] = -inf * (i != j);
rep(st, 0, 9) if (u & (1 << st)){
x ^= 1;
rep(i, 1, n) rep(j, 1, n) c[x][i][j] = -inf;
rep(k, 1, n) rep(i, 1, n) rep(j, 1, n)
c[x][i][j] = max(c[x][i][j], c[x ^ 1][i][k] + f[st][k][j]);
} rep(i, 1, n) if (c[x][i][i] > 0) return true;
return false;
} int main(){ scanf("%d%d", &n, &m); rep(st, 0, 9) rep(i, 0, n + 1) rep(j, 0, n + 1) f[st][i][j] = -inf * (int)(i != j);
rep(i, 1, m){
int x, y;
scanf("%d%d", &x, &y);
scanf("%d%d", &f[0][x][y], &f[0][y][x]);
} rep(st, 1, 9){
rep(k, 1, n){
rep(i, 1, n){
rep(j, 1, n){
f[st][i][j] = max(f[st][i][j], f[st - 1][i][k] + f[st - 1][k][j]);
}
}
}
} l = 2, r = n;
if (!check(r)) return 0 * puts("0");
while (l + 1 < r){
int mid = (l + r) >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
} if (check(l)) printf("%d\n", l);
else printf("%d\n", r);
return 0;
}

但是还有更优的办法。

我们可以联想到$O(logn)$求$LCA$时的做法。

$2$的幂次从高到低依次判断,若当前的状态和已经存储的状态结合后可以形成正环,那么恰恰不能取这个幂次。

类比求$LCA$的过程,当$x$往上跳$2^{i}$步后到达的结点和y往上跳$2^{i}$步后到达的结点一样,那么恰恰不能往上跳$2^{i}$步。

我们可以类比这个方法求解这道题最后的答案。

也就是不能形成正环的最大值$ans$

别忘了最后$ans$得加$1$

这样相对前一种方法,复杂度少了一个$log$

时间复杂度$O(n^{3}logn)$

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i) const int inf = 1e9; const int N = 306; int n, m;
int f[10][N][N], c[N][N], g[N][N];
int l, r;
int ans; int main(){ scanf("%d%d", &n, &m); rep(st, 0, 9) rep(i, 0, n + 1) rep(j, 0, n + 1) f[st][i][j] = g[i][j] = -inf * (int)(i != j);
rep(i, 1, m){
int x, y;
scanf("%d%d", &x, &y);
scanf("%d%d", &f[0][x][y], &f[0][y][x]);
} rep(st, 1, 9){
rep(k, 1, n){
rep(i, 1, n){
rep(j, 1, n){
f[st][i][j] = max(f[st][i][j], f[st - 1][i][k] + f[st - 1][k][j]);
}
}
}
} ans = 0;
dec(st, 9, 0){
rep(i, 0, n + 1) rep(j, 0, n + 1) c[i][j] = -inf;
rep(k, 1, n) rep(i, 1, n) rep(j, 1, n) c[i][j] = max(c[i][j], g[i][k] + f[st][k][j]);
bool flag = false;
rep(i, 1, n) if (c[i][i] > 0){ flag = true; break;}
if (!flag){
ans += 1 << st;
rep(i, 0, n + 1) rep(j, 0, n + 1) g[i][j] = c[i][j];
}
} ++ans;
printf("%d\n", ans > n ? 0 : ans);
return 0;
}

  

  

Codeforces 147B Smile House(DP预处理 + 倍增)的更多相关文章

  1. Codeforces 980E The Number Games 贪心 倍增表

    原文链接https://www.cnblogs.com/zhouzhendong/p/9074226.html 题目传送门 - Codeforces 980E 题意 $\rm Codeforces$ ...

  2. [Codeforces 1201D]Treasure Hunting(DP)

    [Codeforces 1201D]Treasure Hunting(DP) 题面 有一个n*m的方格,方格上有k个宝藏,一个人从(1,1)出发,可以向左或者向右走,但不能向下走.给出q个列,在这些列 ...

  3. Gym101889J. Jumping frog(合数分解+环形dp预处理)

    比赛链接:传送门 题目大意: 一只青蛙在长度为N的字符串上跳跃,“R”可以跳上去,“P”不可以跳上去. 字符串是环形的,N-1和0相连. 青蛙的跳跃距离K的取值范围是[1, N-1],选定K之后不可改 ...

  4. Educational Codeforces Round 59 (Rated for Div. 2) E 区间dp + 状态定义 + dp预处理(分步dp)

    https://codeforces.com/contest/1107/problem/E 题意 给出01字符串s(n<=100),相邻且相同的字符可以同时消去,一次性消去i个字符的分数是\(a ...

  5. Codeforces#572 Div2 C---Candies!【倍增】【DP】【思维】

    题目:http://codeforces.com/contest/1189/problem/C 题意:给定n个数,每次查询一个区间$[l,r]$.对这个区间内的数,相邻两个数之和超过10,则得到一个c ...

  6. Palindromic characteristics CodeForces - 835D (区间DP,预处理回文串问题)

    Palindromic characteristics of string s with length |s| is a sequence of |s|integers, where k-th num ...

  7. Codeforces Gym 101194C Mr. Panda and Strips(2016 EC-Final,区间DP预处理 + 枚举剪枝)

    题目链接  2016 EC-Final 题意  现在要找到数列中连续两个子序列(没有公共部分).要求这两个子序列本身内部没有重复出现的数.   求这两个子序列的长度的和的最大值. 首先预处理一下.令$ ...

  8. CodeForces 176B Word Cut dp

    Word Cut 题目连接: http://codeforces.com/problemset/problem/176/C Description Let's consider one interes ...

  9. Codeforces Round #474-E(树形dp)

    一.题目链接 http://codeforces.com/contest/960/problem/B 二.题意 给定一棵$N$个节点的树,每个节点的权值$V$.定义树中两点$u_1$和$u_m$的权值 ...

随机推荐

  1. BFS:Open and Lock(一个数的逐位变化问题的搜索)

    解体心得: 1.关于定义四维数组的问题,在起初使用时,总是在运行时出错,找了很多方法,最后全部将BFS()部分函数写在主函数中,将四维数组定义在主函数中才解决了问题.运行成功后再次将四维数组定义为全局 ...

  2. HDU1301 Jungle Roads

    Jungle Roads The Head Elder of the tropical island of Lagrishan has a problem. A burst of foreign ai ...

  3. opencv使用日记之一:平台搭建Mat类以及图像的读取修改

    平台搭建就摸了一整天时间,真的是...不说了,最后我选择的是 opencv3.0(2015/06/04)  + win7 + vs2012   注意opencv的版本不同导入的库文件是不一样的,所以请 ...

  4. mysql进阶三四五六

    排序查询 一.语法 select 查询表 from 表 where 筛选条件 order by 排序列表[asc / desc] 特点: 1.asc:升序 desc:降序 2.排序列表之中支持单字段, ...

  5. RemoteFX

    RemoteFX 编辑 RemoteFX是微软在Windows 7/2008 R2 SP1中增加的一项桌面虚拟化技术,使得用户在使用远程桌面或虚拟桌面进行游戏应用时,可以获得和本地桌面一致的效果. 外 ...

  6. Couchbase II( View And Index)

    Couchbase II( View And Index)   Views view的作用是从没有结构和半结构的数据对象中抽取过滤需要的信息,并生成相关的index信息,通常生成json数据. vie ...

  7. PostgreSQL 行排序详解

    在查询生成输出表之后,也就是在处理完选择列表之后,你还可以对输出表进行排序. 如果没有排序,那么行将以不可预测的顺序返回(实际顺序将取决于扫描和连接规划类型和在磁盘上的顺序, 但是肯定不能依赖这些东西 ...

  8. 理解机器为什么可以学习(五)---Noise and Error

    之前我们讨论了VC Dimension,最终得到结论,如果我们的hypetheset的VC Dimension是有限的,并且有足够的资料,演算法能够找到一个hypethesis,它的Ein很低的话,那 ...

  9. 聊聊、Tomcat中文乱码和JVM设置

    set JAVA_OPTS=%JAVA_OPTS% -server -Xms512m -Xmx512m -Dfile.encoding=GBK -Dsun.jnu.encoding=GBK

  10. event对象的兼容性

    最近在调试项目的时候,发现IE和Chrome都显示正常,就是FireFox异常,F12查看控制台,发现报错:window.event is undefined.检查代码中定义的事件方法中获取事件对象直 ...