题意
不想写
题解
我们发现n非常小,于是我们可以尝试两两连边
直接连一条x—>y的边表示从x买入,y卖出。。
中途的所有路径都不买卖
然后你就分数规划一下,用SPFA判下负环就可以了
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long LL;
const LL MAX=(1LL<<32);
const LL N=105;
LL n,m,k;
LL A[N][1005],B[N][1005];//每个地方的价钱
LL f[N][N];
bool tf;
bool in[N];
LL dis[N];
LL val[N][N];
void SPFA (LL x,LL XX)
{
in[x]=true;
for (int u=1;u<=n;u++)
{
if (f[x][u]>=MAX) continue ;
if (x==u) continue;
LL y=u;
LL c=f[x][u]*XX-val[x][u];
if (dis[y]>=dis[x]+c)
{
if (in[y]) {tf=true;return ;}
dis[y]=dis[x]+c;
SPFA(y,XX);
}
}
in[x]=false;
}
bool check (LL x)//这么多时间行不行
{
memset(in,false,sizeof(in));
tf=false;
memset(dis,0,sizeof(dis));
for (LL u=1;u<=n;u++)
{
SPFA(u,x);
if (tf) break;
}
return tf;
}
int main()
{
memset(in,false,sizeof(in));
scanf("%lld%lld%lld",&n,&m,&k);
for (LL u=1;u<=n;u++)
for (LL i=1;i<=k;i++)
scanf("%lld%lld",&A[u][i],&B[u][i]);
for (LL u=1;u<=n;u++)
for (LL i=1;i<=n;i++)
{
if (u==i) f[u][i]=0;
else f[u][i]=MAX;
}
for (LL u=1;u<=m;u++)
{
LL x,y,z;
scanf("%lld%lld%lld",&x,&y,&z);
f[x][y]=z;
}
for (LL u=1;u<=n;u++)
for (LL i=1;i<=n;i++)
for (LL j=1;j<=n;j++)
f[i][j]=min(f[i][j],f[i][u]+f[u][j]);
for (LL u=1;u<=n;u++)
for (LL i=1;i<=n;i++)
{
val[u][i]=0;
if (f[u][i]>MAX||u==i) continue;
for (LL j=1;j<=k;j++)
{
if (A[u][j]==-1||B[i][j]==-1) continue;
val[u][i]=max(val[u][i],B[i][j]-A[u][j]);
}
}
//check(1);
LL ans=0;
LL l=1,r=1e9;
while (l<=r)
{
LL mid=(l+r)>>1;
if (check(mid)) {ans=mid;l=mid+1;}
else r=mid-1;
}
printf("%lld\n",ans);
return 0;
}