BZOJ2330: [SCOI2011]糖果
【传送门:BZOJ2330】
简要题意:
有n个小朋友,每一个人都想吃糖,但是有些小朋友之间有攀比风(不要学习),比如说A要比B吃的糖多之类的
给出k个攀比关系,每个关系输入t,x,y,有5种关系:
t=1 x与y吃相同数量的糖果
t=2 x吃的糖果少于y吃的糖果
t=3 x吃的糖果不少于y吃的糖果
t=4 x吃的糖果多于y吃的糖果
t=5 x吃的糖果不多于y吃的糖果
求出最少的糖果数,使得每个小朋友都有糖吃而且满足k个攀比关系
题解:
一眼差分约束
a[i]为第i个小朋友吃的糖果数
约束关系:
t=1 a[x]>=a[y]+0 a[y]>=a[x]+0
t=2 a[y]>=a[x]+1
t=3 a[x]>=a[y]+0
t=4 a[x]>=a[y]+1
t=5 a[y]>=a[x]+0
然后跑最长路就可以了
但是数据有点坑,T了很久,膜了一发hzwer,发现要倒着来进队列,而且要加long long
参考代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<cmath> using namespace std; typedef long long LL; int list[1100000]; int ru[210000]; LL d[210000]; bool v[210000]; struct node { int x,y,next; LL d; }a[510000];int len,last[210000]; void ins(int x,int y,LL d) { len++; a[len].x=x;a[len].y=y;a[len].d=d; a[len].next=last[x];last[x]=len; } int main() { int n,m; scanf("%d%d",&n,&m); len=0;memset(last,0,sizeof(last)); for(int i=1;i<=m;i++) { int t,x,y; scanf("%d%d%d",&t,&x,&y); if(t==1) ins(x,y,0),ins(y,x,0); if(t==2) ins(x,y,1); if(t==3) ins(y,x,0); if(t==4) ins(y,x,1); if(t==5) ins(x,y,0); } for(int i=1;i<=n;i++) d[i]=1; int head=0; for(int i=n;i>=1;i--) list[++head]=i; memset(v,false,sizeof(v)); memset(ru,0,sizeof(ru)); while(head!=0) { int x=list[head--]; v[x]=true; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(d[y]<d[x]+a[k].d) { d[y]=d[x]+a[k].d; ru[y]++; if(ru[y]==n) { printf("-1\n"); return 0; } if(v[y]==true) { v[y]=false; list[++head]=y; } } } } LL ans=0; for(int i=1;i<=n;i++) ans+=d[i]; printf("%lld\n",ans); return 0; }
渺渺时空,茫茫人海,与君相遇,幸甚幸甚