Description
幼儿园里有个小朋友,老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果。但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候,需要满足小朋友们的个要求。幼儿园的糖果总是有限的,想知道他至少需要准备多少个糖果,才能使得每个小朋友都能够分到糖果,并且满足小朋友们所有的要求。
Input
输入的第一行是两个整数。
接下来行,表示这些点需要满足的关系,每行3个数字,。
如果, 表示第个小朋友分到的糖果必须和第个小朋友分到的糖果一样多;
如果, 表示第个小朋友分到的糖果必须少于第个小朋友分到的糖果;
如果, 表示第个小朋友分到的糖果必须不少于第个小朋友分到的糖果;
如果, 表示第个小朋友分到的糖果必须多于第个小朋友分到的糖果;
如果, 表示第个小朋友分到的糖果必须不多于第个小朋友分到的糖果.
Output
输出一行,表示老师至少需要准备的糖果数,如果不能满足小朋友们的所有要求,就输出-1。
Sample Input
5 71 1 2
2 3 2
4 4 1
3 4 5
5 4 5
2 3 5
4 5 1
Sample Output
11
HINT
Solution
差分约束系统.
因为"要求每个小朋友都要分到糖果",所以dis[0]=0,0向n个节点都连一条边权为1的边.
且
A向B连一条边权为0的边,B向A连一条边权为0的边.
B向A连一条边权为1的边.
B向A连一条边权为0的边.
跑最长路.
#include<cmath> #include<ctime> #include<stack> #include<queue> #include<cstdio> #include<vector> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define N 100005 #define M 300005 using namespace std; typedef long long ll; struct graph{ int nxt,to,w; }e[M]; ll ans; int g[N],dis[N],tot[N],n,m,cnt; bool inq[N]; queue<int> q; inline void addedge(int x,int y,int w){ e[++cnt].nxt=g[x];g[x]=cnt;e[cnt].to=y;e[cnt].w=w; } inline bool spfa(int u){ q.push(u);inq[u]=true; while(!q.empty()){ u=q.front();q.pop();inq[u]=false; for(int i=g[u];i;i=e[i].nxt) if(dis[u]+e[i].w>dis[e[i].to]){ dis[e[i].to]=dis[u]+e[i].w; if(!inq[e[i].to]){ if(++tot[e[i].to]>n) return false; inq[e[i].to]=true;q.push(e[i].to); } } } return true; } inline void init(){ scanf("%d%d",&n,&m); for(int i=1,x,a,b;i<=m;++i){ scanf("%d%d%d",&x,&a,&b); if(x==1){ addedge(a,b,0);addedge(b,a,0); } else if(x==2) addedge(a,b,1); else if(x==3) addedge(b,a,0); else if(x==4) addedge(b,a,1); else addedge(a,b,0); } for(int i=n;i;--i) addedge(0,i,1); if(!spfa(0)) puts("-1"); else{ for(int i=1;i<=n;++i) ans+=(ll)(dis[i]); printf("%lld ",ans); } } int main(){ freopen("candy.in","r",stdin); freopen("candy.out","w",stdout); init(); fclose(stdin); fclose(stdout); return 0; }