显然的差分约束
要求最小值
那就要用 ≥ 号来表示每个小朋友之间的关系
边 ( u,v ) 的权值 x 表示 u 小朋友要比 v 小朋友多 x 个糖
然后跑最长路
如果有正环说明无法满足所有人的要求(A比B多,B比C多,C又要比A多这样的环)
然后因为毒瘤的数据
1.要特判一波小朋友的无理要求(自己的糖要比自己少什么的...)
2.建一个虚节点,连接每个小朋友时从 n 到 1 连(不然会T...)
然后注意每个小朋友至少要一个糖
所以虚节点连接小朋友时权值要为1
最后答案就是每个小朋友的 dis 值之和(每个小朋友的 dis 表示 ta 最少要多少个糖)
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> using namespace std; inline int read() { int x=0; char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); return x; } const int N=1e6+7; int n,m; int fir[N],from[N],to[N],val[N],cnt; inline void add(int a,int b,int c) { from[++cnt]=fir[a]; fir[a]=cnt; to[cnt]=b; val[cnt]=c; } //SPFA模板 int dis[N],tot[N];//tot记录一个点进入队列的次数,如果大于节点总数说明有正环 bool vis[N],flag; queue <int> q; void SPFA() { q.push(0); dis[0]=0; vis[0]=1; while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=0; if(++tot[u]>=n) { flag=1; break; } for(int i=fir[u];i;i=from[i]) { int &v=to[i]; if(dis[v]<dis[u]+val[i]) { dis[v]=dis[u]+val[i]; if(!vis[v]) q.push(v),vis[v]=1; } } } } int main() { int a,b,c; n=read(); m=read(); for(int i=1;i<=m;i++) { a=read(); b=read(); c=read(); if(a==1) add(b,c,0),add(c,b,0); if(a==2) { if(b==c) { flag=1; break; }//特判一波小朋友的无理要求 add(b,c,1); } if(a==3) add(c,b,0); if(a==4) { if(b==c) { flag=1; break; } add(c,b,1); } if(a==5) add(b,c,0); } for(int i=n;i;i--) add(0,i,1);//for要从n到1,毒瘤数据... if(flag) { cout<<-1; return 0; } SPFA(); if(flag) { cout<<-1; return 0; } long long ans=0;//ans要用long long 存 for(int i=1;i<=n;i++) ans+=dis[i]; printf("%lld",ans); return 0; }