agc036D - Negative Cycle
题目大意
题解
过于巧妙
关键点:无负环=差分约束有解
由于有i->i+1的0边,所以fi>=fi+1,又因为边的绝对值不超1,所以fi<=(fi+1)+1
设f[i][j]表示当前f相同的段是[j+1,i],枚举下一段结尾k转移,负边不能连同一个块,正边只能连同块和相邻两个块的
code
#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define ll long long
//#define file
using namespace std;
ll a[502][502],b[502][502],f[501][501],ans,sum;
int n,i,j,k,l;
int main()
{
#ifdef file
freopen("agc036d.in","r",stdin);
#endif
scanf("%d",&n);
fo(i,1,n)
{
fo(j,1,n)
if (i!=j)
scanf("%lld",&a[i][j]),b[i][j]=a[i][j]*(i>j),a[i][j]*=(i<j);
}
fo(i,1,n) fo(j,1,n) a[i][j]+=a[i-1][j]+a[i][j-1]-a[i-1][j-1],b[i][j]+=b[i-1][j]+b[i][j-1]-b[i-1][j-1];
memset(f,128,sizeof(f));
fo(i,1,n)
{
f[i][0]=b[i][i];
fo(j,0,i-1)
{
fo(k,i+1,n)
f[k][i]=max(f[k][i],f[i][j]+(a[i][k]-a[i][i])+((b[k][k]-b[i][k])-(b[k][j]-b[i][j])));
}
}
ans=0;
fo(i,0,n-1) ans=max(ans,f[n][i]);
ans=a[n][n]+b[n][n]-ans;
printf("%lld\n",ans);
fclose(stdin);
fclose(stdout);
return 0;
}