bzoj 2330(差分約束)
阿新 • • 發佈:2019-01-27
傳送門
題意:略
差分約束後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;
}