1. 程式人生 > >bzoj 2330(差分約束)

bzoj 2330(差分約束)

傳送門
題意:略
差分約束後SPFA求最長路,注意判環和輸入時特殊不合法情況(某人拿的糖果不能多於自己)

P.S.競賽生兩週的暑假結束前最後做點題壓壓驚╮(╯▽╰)╭

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+2;
int n,m;
int dis[maxn],in[maxn];
bool vis[maxn];
int head[maxn],edge=0;
struct EDGE {
    int v,w,nxt;
}e[maxn<<1
]; queue<int> q; inline int read() { int x=0;char c=getchar(); while (c<'0'||c>'9') c=getchar(); while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); return x; } inline void adde(int u,int v,int w) { e[edge].nxt=head[u],e[edge].v=v,e[edge].w=w,head[u]=edge++; } inline
bool spfa() { while (!q.empty()) { int p=q.front();q.pop();vis[p]=0; for (int i=head[p];~i;i=e[i].nxt) { int v=e[i].v; if (dis[v]<dis[p]+e[i].w) { dis[v]=dis[p]+e[i].w; if (!vis[v]) { vis[v]=1; q.push(v); if
(++in[v]>=n) return false; } } } } return true; } int main() { // freopen("bzoj 2330.in","r",stdin); memset(head,-1,sizeof(head)); memset(in,0,sizeof(in)); n=read(),m=read(); for (register int i=1;i<=m;++i) { int opt=read(),a=read(),b=read(); switch (opt) { case 1:adde(a,b,0),adde(b,a,0);break; case 2:if (a==b) {puts("-1");return 0;}adde(a,b,1);break; case 3:adde(b,a,0);break; case 4:if (a==b) {puts("-1");return 0;}adde(b,a,1);break; case 5:adde(a,b,0);break; } } for (register int i=1;i<=n;++i) vis[i]=dis[i]=1,q.push(i); if (!spfa()) {puts("-1");return 0;} ll ans=0; for (register int i=1;i<=n;++i) ans+=(ll)dis[i]; printf("%lld\n",ans); return 0; }