差分约束系统,题意非常明显,比较简单。
1、题目中有冲突的数据需要特判。
2、注意读题:每个小朋友都必须分到糖果,所以最后的答案要加n
3、注意差分约束系统有两种形式:最长路和最短路(对应≥和≤);
其中最长路解出来的结果是最小值,最短路解出来的结果是最大值。(都是接近常数);
要根据题意选取适当的形式;
1 #include <cstdio> 2 #include <cstdlib> 3 #include <queue> 4 #include <cstring> 5 #define S n+1 6 #define N 100000+10 7 #define M 1000000+10 8 #define INF 9999999 9 using namespace std; 10 //Global 11 int head[N],next[M],e[M],w[M],countside=1; 12 int n,k; 13 //Function 14 void buildside(int a,int b,int c){ 15 e[countside]=b; 16 w[countside]=c; 17 next[countside]=head[a]; 18 head[a]=countside; 19 countside++; 20 } 21 int spfa(int s){ 22 int i,relax[N]; 23 bool inq[N]; 24 int dis[N]; 25 memset(inq,false,sizeof(inq)); 26 memset(relax,0,sizeof(relax)); 27 for (i=1;i<=n+10;i++) 28 dis[i]=-INF; 29 dis[s]=0; 30 queue<int> q; 31 q.push(s); 32 inq[s]=true; 33 while (!q.empty()){//printf("outed"); 34 int now=q.front(); 35 q.pop(); 36 inq[now]=false; 37 for (i=head[now];i>0;i=next[i]){ 38 if (dis[e[i]]<dis[now]+w[i]){ 39 dis[e[i]]=dis[now]+w[i]; 40 relax[e[i]]++; 41 if (relax[e[i]]>n+3) return -1; 42 if (!inq[e[i]]){ 43 q.push(e[i]); 44 inq[e[i]]=true; 45 } 46 } 47 } 48 } 49 int ans=0; 50 for (i=1;i<=n;i++) 51 ans+=dis[i]; 52 return ans; 53 } 54 int main() 55 { 56 int i,x,a,b; 57 scanf("%d%d",&n,&k); 58 for (i=1;i<=k;i++) 59 { 60 scanf("%d%d%d",&x,&a,&b); 61 if (x==3) buildside(b,a,0);//xb-xa<=0 62 if (x==5) buildside(a,b,0);//xa-xb<=0 63 if (x==2){ 64 if (a==b) {printf("-1\n");return 0;} 65 buildside(a,b,1);//xa-xb<=-1 66 } 67 if (x==4){ 68 if (a==b) {printf("-1\n");return 0;} 69 buildside(b,a,1);//xb-xa<=-1 70 } 71 if (x==1){ 72 buildside(a,b,0); 73 buildside(b,a,0); 74 //xa-xb<=0&&xb-xa<=0 75 } 76 } 77 for (i=1;i<=n;i++) 78 buildside(S,i,0); 79 int ans=spfa(S); 80 if (ans==-1) printf("-1\n"); 81 else printf("%d\n",ans+n); 82 return 0; 83 }