bzoj2330: [SCOI2011]糖果:http://www.lydsy.com/JudgeOnline/problem.php?id=2330
裸的差分约束 (像我一样不懂差分的萌新先戳这:https://blog.youkuaiyun.com/qq_36038511/article/details/79674502)
因为问最少 推一推跑最长路统计答案就ok
(我输入写错了都有80分 数据真的神奇了)
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct node
{
int x,y,d,next;
}a[2100000];
int last[110000],len;
int d[110000],sta[11000000],ru[110000];
bool v[110000];
void build(int x,int y,int d)
{
len++;
a[len].x=x;a[len].y=y;a[len].d=d;a[len].next=last[x];last[x]=len;
}
int main()
{
int n,k;
scanf("%d%d",&n,&k);
for (int i=1;i<=k;i++)
{
//这是一条最长路 y>=x+c
int u,x,y;
scanf("%d%d%d",&u,&x,&y);
if ((u==2||u==4)&&x==y) {printf("-1\n");return 0;}
if (u==1) {build(x,y,0);build(y,x,0);}//a==b
if (u==2) {build(x,y,1);}//b>a b>=a+1
if (u==3) {build(y,x,0);}//a>=b
if (u==4) {build(y,x,1);} //a>b a>=b+1
if (u==5) {build(x,y,0);} //a<=b b>=a
}
for (int i=n;i>=1;i--) build(0,i,1);//每个小朋友都有糖 i>=0+1
int top=0;
bool bk=false;
memset(v,false,sizeof(v));
memset(d,-0x3f,sizeof(d));
memset(ru,0,sizeof(ru));
d[0]=0;v[0]=true;
for (int i=n;i>=0;i--)
{
sta[++top]=i;
v[i]=true;ru[i]++;
}
while (top>0)
{
int x=sta[top--];
for (int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if (d[y]<d[x]+a[k].d)
{
d[y]=d[x]+a[k].d;
if (v[y]==false)
{
ru[y]++;
if (ru[y]>=n) {bk=true;break;}
v[y]=true;
sta[++top]=y;
}
}
}
v[x]=false;
if (bk) break;
}
if (bk) {printf("-1\n");return 0;}
long long ans=0;
for (int i=1;i<=n;i++) ans+=d[i];
printf("%lld\n",ans);
return 0;
}