答案是分数规划的形式
二分答案
就是求
∑wi∑ti≥x
也就是
∑wi−x⋅ti≥x
用floyd判是否有正环就可以了
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;
const int N=110;
int n,m,k;
int s[N][1010],b[N][1010];
ll w[N][N],t[N][N];
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &x){
char c=nc(); x=0; int f=1;
for(;c>'9'||c<'0';c=nc())if(c=='-')f=-1;for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc()); x*=f;
}
namespace FLOYD{
ll dis[N][N];
bool check(ll x){
memset(dis,-0x7f>>1,sizeof(dis));
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(i!=j)
dis[i][j]=w[i][j]-x*t[i][j];
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
dis[i][j]=max(dis[i][k]+dis[k][j],dis[i][j]);
for(int i=1;i<=n;i++)
if(dis[i][i]>=0) return true;
return false;
}
}
int main(){
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
read(n); read(m); read(k);
for(int i=1;i<=n;i++)
for(int j=1;j<=k;j++)
read(b[i][j]),read(s[i][j]);
memset(t,0x7f>>1,sizeof(t));
for(int i=1,x,y,ti;i<=m;i++)
read(x),read(y),read(ti),t[x][y]=min(t[x][y],(ll)ti);
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
t[i][j]=min(t[i][j],t[i][k]+t[k][j]);
for(int i=1;i<=k;i++){
for(int x=1;x<=n;x++)
for(int y=1;y<=n;y++)
if(~b[x][i] && ~s[y][i]) w[x][y]=max(w[x][y],(ll)s[y][i]-b[x][i]);
}
int kk=FLOYD::check(2);
ll L=1,R=1e9,mid,ans=0;
while(L<=R) FLOYD::check(mid=L+R>>1)?L=(ans=mid)+1:R=mid-1;
printf("%lld\n",ans);
return 0;
}