跑两遍最短路显然是必须的,于是对于每个点\(i\)我们得到了到\(s\)的最短路\(dis_{0,i}\)和到\(t\)的最短路\(dis_{1,i}\),不妨将其看做二维平面上一个坐标为\((dis_{0,i},dis_{1,i})\)的点
不妨再假设一个在\((0,0)\)处的点,两个人轮流移动这个点,\(\rm Tavas\)只能向右移动,\(\rm Nafas\)只能向上移动,每次移动必须框住新的点,这样到最后得到一个阶梯状的图形,这个范围里就是\(\rm Tavas\)的得分
于是我们可以搞一个\(dp\),就是在哪个位置,这一步应该由谁来走,转移的时候需要一个后缀最值来优化,同时记得判断这个转移是否能框住新的点;
代码
#include<bits/stdc++.h>
#define re register
#define LL long long
#define mp std::make_pair
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
const LL inf=1e15;const int maxn=2e3+5;
inline int read() {
char c=getchar();int x=0,r=1;while(c<'0'||c>'9') {if(c=='-') r=-1;c=getchar();}
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x*r;
}
int n,m,s,t,p[maxn],vis[maxn],N,M;
struct E{int v,nxt,w;}e[200005];
int head[maxn],num,ri[maxn],rj[maxn],cnt[maxn][maxn];LL dis[2][maxn],A[maxn];
LL pre[maxn][maxn],dp[maxn][maxn][2],mn[maxn][maxn],mx[maxn][maxn],sum;
typedef std::pair<LL,int> pii;
std::priority_queue<pii,std::vector<pii>,std::greater<pii> > q;
inline void add(int x,int y,int w){e[++num].v=y;e[num].nxt=head[x];head[x]=num;e[num].w=w;}
inline void Dij(LL *d,int S) {
for(re int i=1;i<=n;i++) vis[i]=0,d[i]=inf;
d[S]=0;q.push(mp(0,S));
while(!q.empty()) {
int k=q.top().second;q.pop();
if(vis[k]) continue;vis[k]=1;
for(re int i=head[k];i;i=e[i].nxt)
if(d[e[i].v]>d[k]+e[i].w) d[e[i].v]=d[k]+e[i].w,q.push(mp(d[e[i].v],e[i].v));
}
}
inline void upd(int i,int j) {
mn[i][j]=min(dp[i][j][1],mn[i][j+1]);
mx[i][j]=max(dp[i][j][0]+pre[i][j+1],mx[i+1][j]);
}
signed main() {
n=read(),m=read(),s=read(),t=read();
for(re int i=1;i<=n;i++) p[i]=read(),sum+=p[i];
for(re int x,y,z,i=1;i<=m;i++) {
x=read(),y=read(),z=read();
add(x,y,z),add(y,x,z);
}
Dij(dis[0],s),Dij(dis[1],t);
for(re int i=1;i<=n;i++) A[i]=dis[0][i];
std::sort(A+1,A+n+1);N=std::unique(A+1,A+n+1)-A-1;
for(re int i=1;i<=n;i++) dis[0][i]=std::lower_bound(A+1,A+n+1,dis[0][i])-A;
for(re int i=1;i<=n;i++) A[i]=dis[1][i];
std::sort(A+1,A+n+1);M=std::unique(A+1,A+n+1)-A-1;
for(re int i=1;i<=n;i++) dis[1][i]=std::lower_bound(A+1,A+n+1,dis[1][i])-A;
for(re int i=1;i<=n;i++) pre[dis[0][i]][dis[1][i]]+=p[i],cnt[dis[0][i]][dis[1][i]]++;
for(re int i=1;i<=N+1;i++) for(re int j=M+1;j>=0;j--) pre[i][j]+=pre[i][j+1];
for(re int i=1;i<=N+1;i++) for(re int j=0;j<=M+1;j++) pre[i][j]+=pre[i-1][j];
for(re int i=N+1;i>=0;i--) for(re int j=M+1;j>=0;j--) cnt[i][j]+=cnt[i][j+1];
for(re int i=N+1;i>=0;i--) for(re int j=M+1;j>=0;j--) cnt[i][j]+=cnt[i+1][j];
memset(rj,-1,sizeof(rj));memset(ri,-1,sizeof(ri));
memset(mx,-20,sizeof(mx));memset(mn,20,sizeof(mn));
for(re int i=N;i>=0;i--)
for(re int j=M;j>=0;--j) {
if(cnt[i+1][j+1]==0) {dp[i][j][0]=dp[i][j][1]=0;upd(i,j);continue;}
if(cnt[i+1][j+1]>cnt[i+1][j+2]) ri[i]=j+1;
if(ri[i]!=-1) dp[i][j][0]=mn[i][ri[i]];else dp[i][j][0]=-inf;
if(cnt[i+1][j+1]>cnt[i+2][j+1]) rj[j]=i+1;
if(rj[j]!=-1) dp[i][j][1]=mx[rj[j]][j]-pre[i][j+1];else dp[i][j][1]=inf;
upd(i,j);
}
if(sum-dp[0][0][1]==dp[0][0][1]) puts("Flowers");
if(sum-dp[0][0][1]>dp[0][0][1]) puts("Cry");
if(sum-dp[0][0][1]<dp[0][0][1]) puts("Break a heart");
return 0;
}