BZOJ 2330. [SCOI2011]糖果 題解
阿新 • • 發佈:2021-08-23
題目描述
solve
可以把關係看成是一種約束,然後直接\(SPFA\)刷分差分約束就好了,貌似這道題卡\(SPFA\)看一波題解,發現反建圖就好了
code
#include<bits/stdc++.h> using namespace std; typedef long long LL; const int maxn=100005,maxe=400005; int lnk[maxn],nxt[maxe],son[maxe],w[maxe],dis[maxn],Q[maxn],cnt,vis[maxn],cir[maxn],N,K; LL Ans; inline void add_e(int x,int y,int z){ son[++cnt]=y;w[cnt]=z;nxt[cnt]=lnk[x];lnk[x]=cnt; } inline int read(){ int ret=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();} while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar(); return ret*f; } int SPFA(){ int hed=0,til=1;Q[til]=0;vis[0]=1;cir[0]=1; while(hed!=til){ hed=(hed+1>=maxn?0:hed+1);vis[Q[hed]]=0; for(int j=lnk[Q[hed]];j;j=nxt[j]){ if(dis[Q[hed]]+w[j]>dis[son[j]]){ dis[son[j]]=dis[Q[hed]]+w[j]; if(++cir[son[j]]>=N)return 0; if(!vis[son[j]])vis[son[j]]=1,Q[til=(til+1>=maxn?0:til+1)]=son[j]; } } } return 1; } int main(){ freopen("2330.in","r",stdin); freopen("2330.out","w",stdout); N=read();K=read(); for(int i=1;i<=K;i++){ int X=read(),A=read(),B=read(); if(X==1){add_e(A,B,0);add_e(B,A,0);} else if(X==2){if(A==B){printf("-1\n");return 0;}add_e(A,B,1);} else if(X==3){add_e(B,A,0);} else if(X==4){if(A==B){printf("-1\n");return 0;}add_e(B,A,1);} else if(X==5){add_e(A,B,0);} } for(int i=N;i;i--)add_e(0,i,1); if(!SPFA()){printf("-1\n");return 0;} for(int i=1;i<=N;i++)Ans+=dis[i]; printf("%lld\n",Ans); return 0; }