CF536D. Tavas in Kansas

题目大意

题解

秒了,然后因为没开ll调了一个上午顺便叉掉了两份标

把每个点看做(s到其的最短路,t到其的最短路),等同于在坐标系上有一些点,每次把xy轴向上移,贡献为新扫到的点

离散化,设f[i][j]表示先手扫到i,后手扫到j之后的最大差值,设g表示最小差值

然后用前缀和转移一下即可,注意每次一定要走到至少一个城市

温习了一下dij

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;

struct type{ll x,id;} b[2001];
bool operator < (type a,type b) {return a.x>b.x;}
int a[200001][3],ls[2001],w[2001],sum2[2002][2002],lsf[2002][2002],lsg[2002][2002],h,t,n,m,i,j,k,l,st,ed,x,y,z,len;
ll X[2001],Y[2001],f[2002][2002],g[2002][2002],F[2002][2002],G[2002][2002],sum[2002][2002];
priority_queue<type> heap;

void New(int x,int y,int z) {++len;a[len][0]=y;a[len][1]=ls[x];ls[x]=len;a[len][2]=z;}
bool cmp(type a,type b) {return a.x<b.x;}
void bfs(int st,ll *f)
{
	int i,j,k,l;
	ll s;
	
	memset(f,127,2001*8);f[st]=0;
	heap.push({0,st});
	while (!heap.empty())
	{
		k=heap.top().id;s=heap.top().x;heap.pop();
		if (f[k]<s) continue;
		
		for (i=ls[k]; i; i=a[i][1])
		if (f[a[i][0]]>f[k]+a[i][2])
		f[a[i][0]]=f[k]+a[i][2],heap.push({f[a[i][0]],a[i][0]});
	}
}
void turn(ll *a)
{
	int i,j,k,l;
	
	fo(i,1,n) b[i]={a[i],i};
	sort(b+1,b+n+1,cmp);
	j=0;
	fo(i,1,n) j+=i==1 || b[i].x!=b[i-1].x,a[b[i].id]=j;
}

int main()
{
	#ifdef file
	freopen("CF536D.in","r",stdin);
	#endif
	
	scanf("%d%d",&n,&m);
	scanf("%d%d",&st,&ed);
	fo(i,1,n) scanf("%d",&w[i]);
	fo(i,1,m) scanf("%d%d%d",&x,&y,&z),New(x,y,z),New(y,x,z);
	
	bfs(st,X),bfs(ed,Y);
	turn(X),turn(Y);
	fo(i,1,n) sum[X[i]][Y[i]]+=w[i],++sum2[X[i]][Y[i]];
	fd(i,n,0)
	{
		fd(j,n,0)
		sum[i][j]+=sum[i+1][j]+sum[i][j+1]-sum[i+1][j+1],sum2[i][j]+=sum2[i+1][j]+sum2[i][j+1]-sum2[i+1][j+1];
	}
	
	fd(i,n,0)
	{
		fd(j,n,0)
		{
			lsf[i][j]=lsf[i+1][j];
			lsg[i][j]=lsg[i][j+1];
			
			if (sum2[i+1][j+1])
			{
				f[i][j]=sum[i+1][j+1]+F[lsf[i][j]][j];
				g[i][j]=-sum[i+1][j+1]+G[i][lsg[i][j]];
			}
			F[i][j]=max(F[i+1][j],g[i][j]-sum[i+1][j+1]);
			G[i][j]=min(G[i][j+1],f[i][j]+sum[i+1][j+1]);
			
			if (sum2[i][j+1]>sum2[i+1][j+1]) lsf[i][j]=i;
			if (sum2[i+1][j]>sum2[i+1][j+1]) lsg[i][j]=j;
		}
	}
	if (!f[0][0])
	printf("Flowers\n");
	else
	printf(f[0][0]>0?"Break a heart\n":"Cry\n");
	
	fclose(stdin);
	fclose(stdout);
	return 0;
}

猜你喜欢

转载自www.cnblogs.com/gmh77/p/12813589.html