[bzoj2330][SCOI2011]糖果
来自FallDream的博客,未经允许,请勿转载,谢谢。
幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果。但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候,lxhgww需要满足小朋友们的K个要求。幼儿园的糖果总是有限的,lxhgww想知道他至少需要准备多少个糖果,才能使得每个小朋友都能够分到糖果,并且满足小朋友们所有的要求。
输入的第一行是两个整数N,K。
接下来K行,表示这些点需要满足的关系,每行3个数字,X,A,B。
如果X=1, 表示第A个小朋友分到的糖果必须和第B个小朋友分到的糖果一样多;
如果X=2, 表示第A个小朋友分到的糖果必须少于第B个小朋友分到的糖果;
如果X=3, 表示第A个小朋友分到的糖果必须不少于第B个小朋友分到的糖果;
如果X=4, 表示第A个小朋友分到的糖果必须多于第B个小朋友分到的糖果;
如果X=5, 表示第A个小朋友分到的糖果必须不多于第B个小朋友分到的糖果;
n,m<=100000
比较裸的差分约束 建图之后最短/最长路
为了保证所有小朋友获得的糖果大于0,可以新建一个点,向所有点连1.
但是注意千万不要直接spfa判环,貌似有个链数据会T,靠谱做法是直接让所有点距离为1,然后放进去spfa,不建那个点了233。
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #define ll long long #define INF 2000000000 #define MN 100000 using namespace std; inline int read() { int x = 0 , f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar();} while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();} return x * f; } ll ans=0; int head[MN+5],cnt=0,n,m,q[MN+5],top,d[MN+5],c[MN+5],mx=0; struct edge{int to,next,w;}e[MN*5+5]; bool inq[MN+5],mark[MN+5]; queue<int> qu; inline void ins(int f,int t,int w){e[++cnt]=(edge){t,head[f],w};head[f]=cnt;} bool spfa() { while(!qu.empty()) { int now=qu.front();c[now]++;qu.pop(); if(!mark[now]) q[++top]=now,mark[now]=1; if(c[now]>1000) return false; for(int j=head[now];j;j=e[j].next) if(d[now]+e[j].w>d[e[j].to]) { d[e[j].to]=d[now]+e[j].w; if(!inq[e[j].to]) { qu.push(e[j].to); inq[e[j].to]=1; } } inq[now]=0; } return true; } int main() { memset(d,128,sizeof(d)); n=read();m=read(); for(int i=1;i<=m;i++) { int x=read(),u=read(),v=read(); if(u==v&&!(x&1)) return 0*puts("-1"); if(x==1) ins(u,v,0),ins(v,u,0); if(x==2) ins(u,v,1); if(x==3) ins(v,u,0); if(x==4) ins(v,u,1); if(x==5) ins(u,v,0); } for(int i=1;i<=n;i++) qu.push(i),inq[i]=1,d[i]=1; if(!spfa()) return 0*puts("-1"); for(int i=1;i<=n;i++) ans+=d[i]; printf("%lld\n",ans); return 0; }
FallDream代表秋之国向您问好!
欢迎您来我的博客www.cnblogs.com/FallDream