题目链接:
明显的一个差分约束模型。
设(C_i)表示小朋友(i)有的糖果数,那么有如下连边方式:
-
(X=1)
- 因为(C_A=C_B),有(C_Age C_B+0,C_Bge C_A+0),连边((A,B,0),(B,A,0))
-
(X=2)
- 因为(C_A<C_B),有(C_Bge C_A+1),连边((A,B,1))
那么同理:
-
(X=3),连边((B,A,0))
-
(X=4),连边((B,A,1))
-
(X=5),连边((A,B,0))
需要注意,若(Xin{2,4})且(A ot=B),则无解。
然后判正环即可。
最后的答案?
因为每个人都要有糖,将所有节点初始距离设为(1),跑一遍最长路即为答案。
时间复杂度 (O(nk))
#include <queue>
#include <cstdio>
int n,k;
int Head[100005],Next[200005],Val[200005],To[200005],En;
int Cnt[100005],Dis[100005];
bool v[100005];
std::queue<int> q;
void Add(int x,int y,int z)
{
Next[++En]=Head[x];
Head[x]=En;
To[En]=y;
Val[En]=z;
}
bool SPFA()
{
while(!q.empty())
{
int x=q.front();
q.pop();
v[x]=0;
for(int i=Head[x];i;i=Next[i])
{
int y=To[i];
if(Dis[y]<Dis[x]+Val[i])
{
Dis[y]=Dis[x]+Val[i];
if(++Cnt[y]==n)return false;
if(!v[y])v[y]=1,q.push(y);
}
}
}
return true;
}
int main()
{
scanf("%d%d",&n,&k);
while(k--)
{
int op,a,b;
scanf("%d%d%d",&op,&a,&b);
if(op==1)Add(a,b,0),Add(b,a,0);
else if(op==2)Add(a,b,1);
else if(op==3)Add(b,a,0);
else if(op==4)Add(b,a,1);
else Add(a,b,0);
if(!(op&1)&&a==b)return puts("-1"),0;
}
for(int i=1;i<=n;++i)v[i]=Dis[i]=1,q.push(i);
if(!SPFA())return puts("-1"),0;
long long Ans=0;
for(int i=1;i<=n;++i)Ans+=Dis[i];
return printf("%lld
",Ans),0;
}