1. 程式人生 > >bzoj2330糖果——差分約束

bzoj2330糖果——差分約束

{} 什麽 bool href ble AR pre max 題目

題目:https://www.lydsy.com/JudgeOnline/problem.php?id=2330

差分約束,再建立一個源點0,向所有點連邊權為1的邊,表示每個人都會分到糖果;

答案較大,需要開long long;

據說有個大數據會T,所以需要0點從n向1連邊;

WA了數次,竟然是沒看清條件...不少於,不多於什麽的...

代碼如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
queue<int>q;
int const MAXN=1e5+5; int n,k,head[MAXN],ct,dis[MAXN],cnt[MAXN]; bool in[MAXN]; long long ans; struct N{ int to,next,w; N(int t=0,int n=0,int w=0):to(t),next(n),w(w) {} }edge[MAXN<<2]; bool spfa(int s) { memset(in,0,sizeof in); memset(dis,-3,sizeof dis); dis[s]=0;in[s]=1;q.push(s);cnt[s]=1
; while(q.size()) { int x=q.front();q.pop();in[x]=0; for(int i=head[x],u;i;i=edge[i].next) { if(dis[u=edge[i].to]<dis[x]+edge[i].w) { if(++cnt[u]>=n)return 0; dis[u]=dis[x]+edge[i].w; if(!in[u])in
[u]=1,q.push(u); } } } return 1; } int main() { scanf("%d%d",&n,&k); int tp,x,y; for(int i=1;i<=k;i++) { scanf("%d%d%d",&tp,&x,&y); if(tp==1){edge[++ct]=N(y,head[x],0),head[x]=ct; edge[++ct]=N(x,head[y],0),head[y]=ct;} if(tp==2){if(x==y){printf("-1");return 0;} else edge[++ct]=N(y,head[x],1),head[x]=ct;} if(tp==3)edge[++ct]=N(x,head[y],0),head[y]=ct; if(tp==4){if(x==y){printf("-1");return 0;} else edge[++ct]=N(x,head[y],1),head[y]=ct;} if(tp==5)edge[++ct]=N(y,head[x],0),head[x]=ct; } for(int i=n;i;i--) edge[++ct]=N(i,head[0],1),head[0]=ct; if(!spfa(0)) { printf("-1");return 0; } for(int i=1;i<=n;i++)ans+=dis[i]; printf("%lld",ans); return 0; }

bzoj2330糖果——差分約束