bzoj4773
矩阵乘法
。。。爆零了。。。
想到Floyd,却不知道怎么限制点数。。。
其实我们只要给Floyd加一维,dp[i][j][k]表示当前走过了i个点,从j到k的最短距离,然后这样可以倍增,最后看是否有i->i的距离<0
做dp或最短路之类的题的时候,如果限制条件较多,可以考虑加维度
#include<bits/stdc++.h> using namespace std; const int N = 305; int n, m, ans; int Log[N]; struct matrix { int a[N][N]; matrix() { memset(a, 0x3f3f, sizeof(a)); } friend matrix operator * (const matrix &a, const matrix &b) { matrix ret; for(int k = 1; k <= n; ++k) for(int i = 1; i <= n; ++i) for(int j = 1; j <= n; ++j) ret.a[i][j] = min(ret.a[i][j], a.a[i][k] + b.a[k][j]); return ret; } } A[N], tmp; bool judge(const matrix &a) { for(int i = 1; i <= n; ++i) if(a.a[i][i] < 0) return true; return false; } int main() { scanf("%d%d", &n, &m); for(int i = 1; i <= n; ++i) A[0].a[i][i] = tmp.a[i][i] = 0; for(int i = 1, u, v, w; i <= m; ++i) scanf("%d%d%d", &u, &v, &w), A[0].a[u][v] = w; Log[1] = 1; for(int i = 2; i <= n; ++i) Log[i] = Log[i >> 1] + 1; for(int i = 1; i <= Log[n]; ++i) A[i] = A[i - 1] * A[i - 1]; for(int i = Log[n]; i >= 0; --i) if(!judge(A[i] * tmp)) tmp = tmp * A[i], ans += 1 << i; tmp = tmp * A[0]; printf("%d\n", judge(tmp) ? ans + 1 : 0); return 0; }