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;
}
View Code

 

posted @ 2017-10-23 23:11  19992147  阅读(163)  评论(0编辑  收藏  举报