2018-Sp27-lyk/E
从 Trac 迁移的文章
这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。
原文章内容如下:
{{{
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL INF = 1E18;
void print(LL x){
printf(x < 0 ? " -INF" : "%6lld", x);
}
#define maxn 129
bool g[maxn][maxn];
LL w[maxn];
LL n, m, t, T;
struct matrix{
LL d[maxn][maxn];
matrix(){
//初始化power(0)
for(int i = 0; i <= 2 * n; i += 1)
for(int j = 0; j <= 2 * n; j += 1)
d[i][j] = i == j ? 0 : -INF;
for(int i = 0; i < n; i += 1)
for(int j = 0; j < n; j += 1)
d[j + n][i] = 0;
}
matrix operator * (const matrix & b){
//矩阵乘法
matrix res;
for(int k = 0; k <= 2 * n; k += 1)
for(int i = 0; i <= 2 * n; i += 1)
for(int j = 0; j <= 2 * n; j += 1)
res.d[i][j] = max(res.d[i][j], d[i][k] + b.d[k][j]);
return res;
}
void out(int n){
for(int i = 0; i < n; i += 1){
for(int j = 0; j < n; j += 1) print(d[i][j]);
printf("\n");
}
printf("\n");
}
}one;
matrix power(LL r){
//矩阵快速幂
//power(r).d[i][j]表示从点i到点j(但没有走到j)至多r步点权值最大和
//需要额外标号为2*n的点
//power(r).d[i][2*n],表示从点i到某个点至多r步点权值最大和
matrix res, a = one;
for(; r; r >>= 1, a = a * a) if(r & 1) res = res * a;
return res;
}
int main(){
scanf("%lld %lld %lld %lld", &n, &m, &t, &T);
for(int i = 0; i < m; i += 1){
int u, v;
scanf("%d %d", &u, &v);
g[u - 1][v - 1] = true;
}
for(int i = 0; i < n; i += 1){
scanf("%lld", w + i);
w[i + n] = w[i];
}
//初始化power(1)
for(int i = 0; i < n; i += 1)
for(int j = 0; j < n; j += 1){
if(i != j) one.d[i][j] = one.d[i + n][j + n] = -INF;
if(g[i][j]) one.d[i][j] = one.d[i + n][j + n] = w[i];
}
for(int i = 0; i < n; i += 1)
for(int j = 0; j < n; j += 1){
one.d[i][j + n] = -INF;
one.d[i + n][j] = w[i];
}
for(int i = 0; i < 2 * n; i += 1){
one.d[i][2 * n] = w[i];
one.d[2 * n][i] = -INF;
}
matrix db = power(T);
matrix sg = power(t - T);
LL ans = -INF;
for(int i = 0; i < n; i += 1)
for(int j = 0; j < n; j += 1){
ans = max(ans, db.d[i][j] * 2 + sg.d[j + n][i]);
//需要考虑翻倍后不再走的情况
ans = max(ans, db.d[i][2 * n] * 2 + sg.d[j][i]);
}
printf("%lld\n", ans);
}
}}}
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL INF = 1E18;
void print(LL x){
printf(x < 0 ? " -INF" : "%6lld", x);
}
#define maxn 129
bool g[maxn][maxn];
LL w[maxn];
LL n, m, t, T;
struct matrix{
LL d[maxn][maxn];
matrix(){
//初始化power(0)
for(int i = 0; i <= 2 * n; i += 1)
for(int j = 0; j <= 2 * n; j += 1)
d[i][j] = i == j ? 0 : -INF;
for(int i = 0; i < n; i += 1)
for(int j = 0; j < n; j += 1)
d[j + n][i] = 0;
}
matrix operator * (const matrix & b){
//矩阵乘法
matrix res;
for(int k = 0; k <= 2 * n; k += 1)
for(int i = 0; i <= 2 * n; i += 1)
for(int j = 0; j <= 2 * n; j += 1)
res.d[i][j] = max(res.d[i][j], d[i][k] + b.d[k][j]);
return res;
}
void out(int n){
for(int i = 0; i < n; i += 1){
for(int j = 0; j < n; j += 1) print(d[i][j]);
printf("\n");
}
printf("\n");
}
}one;
matrix power(LL r){
//矩阵快速幂
//power(r).d[i][j]表示从点i到点j(但没有走到j)至多r步点权值最大和
//需要额外标号为2*n的点
//power(r).d[i][2*n],表示从点i到某个点至多r步点权值最大和
matrix res, a = one;
for(; r; r >>= 1, a = a * a) if(r & 1) res = res * a;
return res;
}
int main(){
scanf("%lld %lld %lld %lld", &n, &m, &t, &T);
for(int i = 0; i < m; i += 1){
int u, v;
scanf("%d %d", &u, &v);
g[u - 1][v - 1] = true;
}
for(int i = 0; i < n; i += 1){
scanf("%lld", w + i);
w[i + n] = w[i];
}
//初始化power(1)
for(int i = 0; i < n; i += 1)
for(int j = 0; j < n; j += 1){
if(i != j) one.d[i][j] = one.d[i + n][j + n] = -INF;
if(g[i][j]) one.d[i][j] = one.d[i + n][j + n] = w[i];
}
for(int i = 0; i < n; i += 1)
for(int j = 0; j < n; j += 1){
one.d[i][j + n] = -INF;
one.d[i + n][j] = w[i];
}
for(int i = 0; i < 2 * n; i += 1){
one.d[i][2 * n] = w[i];
one.d[2 * n][i] = -INF;
}
matrix db = power(T);
matrix sg = power(t - T);
LL ans = -INF;
for(int i = 0; i < n; i += 1)
for(int j = 0; j < n; j += 1){
ans = max(ans, db.d[i][j] * 2 + sg.d[j + n][i]);
//需要考虑翻倍后不再走的情况
ans = max(ans, db.d[i][2 * n] * 2 + sg.d[j][i]);
}
printf("%lld\n", ans);
}