幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果。但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候,lxhgww需要满足小朋友们的K个要求。幼儿园的糖果总是有限的,lxhgww想知道他至少需要准备多少个糖果,才能使得每个小朋友都能够分到糖果,并且满足小朋友们所有的要求。
标签:
幼儿园里有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个小朋友分到的糖果;
输出一行,表示lxhgww老师至少需要准备的糖果数,如果不能满足小朋友们的所有要求,就输出-1。
【数据范围】
对于30%的数据,保证 N<=100
对于100%的数据,保证 N<=100000
对于所有的数据,保证 K<=100000,1<=X<=5,1<=A, B<=N
【思路】
差分约束系统。
对于op:
1:A=B -> A>=B,B>=A
2:A<B -> B>=A+1
3:A>=B
4:A>B -> A>=B+1
5:A<=B
根据上述条件连边,spfa求最长路判断有无正权环即可。因为每个人都要分得糖果,所以由超级源0点向每个点连长为1的边,最后答案为最短路之和。
需要注意的是,数据中有链的情况,如果使用边表需要倒序加入如果使用vector的方式(姑且这么叫吧+-+)需要正序加入,目的是使按照1-n的顺序进行spfa,以免时间退化为O(n^2)。
【代码】
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #include<queue> 5 using namespace std; 6 7 const int maxn = 100000+10; 8 const int INF = 1e9; 9 10 struct Edge { int u,v,w; 11 }; 12 vector<int> G[maxn]; 13 vector<Edge> es; 14 void addedge(int u,int v,int w) { 15 es.push_back((Edge){u,v,w}); 16 int m=es.size(); G[u].push_back(m-1); 17 } 18 int n,m; 19 queue<int> q; 20 int inq[maxn],d[maxn],cnt[maxn]; 21 bool spfa() { 22 for(int i=1;i<=n;i++) d[i]=1,q.push(i); //直接加点 23 while(!q.empty()) { 24 int u=q.front(); q.pop(); inq[u]=0; 25 for(int i=0;i<G[u].size();i++) { 26 Edge e=es[G[u][i]]; 27 int v=e.v; 28 if(d[v]<d[u]+e.w) { 29 d[v]=d[u]+e.w; 30 if(!inq[v]) { 31 inq[v]=1 , q.push(v); 32 if(++cnt[v]>(n)) return false; 33 } 34 } 35 } 36 } 37 return true; 38 } 39 40 int main() { 41 scanf("%d%d",&n,&m); 42 int u,v,w; 43 for(int i=0;i<m;i++) { 44 scanf("%d%d%d",&w,&u,&v); 45 switch(w) { 46 case 1: 47 addedge(u,v,0),addedge(v,u,0); break; 48 case 2: 49 if(u==v) { puts("-1"); return 0; } 50 addedge(u,v,1); break; 51 case 3: 52 addedge(v,u,0); 53 break; 54 case 4: 55 if(u==v) { puts("-1"); return 0; } 56 addedge(v,u,1); break; 57 case 5: 58 addedge(u,v,0); break; 59 } 60 } 61 bool ans=spfa(); 62 if(!ans) puts("-1"); 63 else { 64 long long tot=0; 65 for(int i=1;i<=n;i++) tot+=(long long ) d[i]; 66 printf("%lld\n",tot); 67 } 68 return 0; 69 }
bzoj 2330 [SCOI2011]糖果(差分约束系统)
标签:
原文地址:http://www.cnblogs.com/lidaxin/p/5095878.html