https://nanti.jisuanke.com/t/A1108
本题又叫缺点最短路,数据卡的很好,
一N×N×N×N恰好过不了
二N×N×N×logN才行
如果一的话就可以再在floyed的基础上多枚举一维
这一维表示不经过该点
floyed的本质是一个增量算法,最外一维枚举的是k,但这个顺序并不影响最后的结果
如果可以处理处对于每个点Y,只剩Y没在floyed的转移矩阵里,
这个矩阵的值就是不经过 y 点的全源最短路
考虑分治,
为什么要分治呢
因为一算法的不好在于每次排除一个点都要所有都枚举一次,很多状态都是重复计算的,
比如总共有10个点,先排除点1,再排除点2,明显两次其他八个点都只用算一次就行了,而一算法,就会多次计算
而分治,可以保证每个只算一次,要用的时候就把其他八个拼起来(因为顺序不重要)
每一次把点集拆成两半,
每一次把点集拆成两半,
先用前一半的点在 Floyd 算法中滚,再递归后一半点。
然后回溯,用后一半的点在 Floyd 算法里滚,递归前一半的点。
这样每个只有一个点的状态得到的就是只有这个点没有在 Floyd 算法里滚的矩阵
如果实在理解不到的话,代码里有个注释打开,
4
0 1 -1 -1
-1 0 1 -1
-1 -1 0 1
1 -1 -1 0
输出是
l=1 r=4
l=3 r=4
l=4 r=4
l=3 r=3
l=1 r=2
l=2 r=2
l=1 r=1
4
code by std:
#include
#include
#include
#include
#include
#include
using namespace std;
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
inline void read(int &x)
{
x = 0;char ch = getchar(), c = ch;
while(ch < '0' || ch > '9')c = ch, ch = getchar();
while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar();
if(c == '-')x = -x;
}
const int INF = 0x3f3f3f3f;
const int MAXN = 300 + 10;
int g[MAXN][MAXN],n;
long long ans;
void solve(int l, int r)
{
//cout<<"l="<