传送门:糖果
思路:鉴定为——裸题
当x==1时,关系为 :a>=b && b>=a,所以add(a,b,0),add(b,a,0)两条边;
当x==2时 ,为 b>=a+1,add(a,b,1)
当x==3时,为a>=b ,add(b,a,0)
当x==4时,为a>=b+1,add(b,a,1)
当x==5时,为b>=a, add(a,b,0)
因为是求最小值,所以要用求最长路的下界来求,到此为止分析的都是相对关系,而根据题目中的每个小朋友都必须分到糖果,可以得出任意的xi>=1,到此,可以设置一个虚拟源点0,连向所有的点,长度为1.
另外:这道题目里面不能用队列,需要用栈,否则会超时。
代码:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<stack>
using namespace std;
typedef long long ll;
int n,m;
const int N=1e5+10,M=3e5+10;
int e[M],ne[M],h[N],w[M],idx;
ll dist[N];
bool st[N];
int cnt[N];
int q[N];
void add(int a,int b,int c)
{
e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}
bool spfa()
{
int hh=0,tt=1;
memset(dist,-0x3f,sizeof dist);
dist[0]=0;
st[0]=true;
while(hh!=tt)
{
int t=q[--tt];
// if(hh==N) hh=0;
st[t]=false;
for(int i=h[t];~i;i=ne[i])
{
int j=e[i];
if(dist[j]<dist[t]+w[i])
{
dist[j]=dist[t]+w[i];
cnt[j]=cnt[t]+1;
if(cnt[j]>=n+1) return false;
if(!st[j])
{
q[tt++]=j;
// if(tt==N) tt=0;
st[j]=true;
}
}
}
}
return true;
}
int main()
{
memset(h,-1,sizeof h);
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int a,b,c;
scanf("%d%d%d",&c,&a,&b);
if(c==1)
{
add(a,b,0);
add(b,a,0);
}else if(c==2) add(a,b,1);
else if(c==3) add(b,a,0);
else if(c==4) add(b,a,1);
else add(a,b,0);
}
for(int i=1;i<=n;i++)
add(0,i,1);
if(!spfa()) puts("-1");
else
{
ll sum=0;
for(int i=1;i<=n;i++)
sum+=dist[i];
printf("%lld\n",sum);
}
return 0;
}