[bzoj2330]糖果
对于所有限制,都可以写成形如$di>=dj+c$的形式(等式看成两个),然后这个东西很显然就是一张图的一条边,然后求最长路即可(当c为负移项即可)
由于每一个人都要有糖,所以让di初始为1并入队即可
(注意:最好判掉自环,可以快很多,如果不判在spfa时应将标记清空放在前面,否则就找不到自环了)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 100005 4 struct ji{ 5 int nex,to,len; 6 }edge[N<<1]; 7 queue<int>q; 8 int E,n,m,p,x,y,head[N],d[N],vis[N],sum[N]; 9 long long ans; 10 void add(int x,int y,int z){ 11 edge[E].nex=head[x]; 12 edge[E].to=y; 13 edge[E].len=z; 14 head[x]=E++; 15 } 16 bool spfa(){ 17 for(int i=1;i<=n;i++){ 18 q.push(i); 19 vis[i]=d[i]=1; 20 } 21 while (!q.empty()){ 22 int k=q.front(); 23 q.pop(); 24 vis[k]=0; 25 for(int i=head[k];i!=-1;i=edge[i].nex){ 26 int v=edge[i].to; 27 if (d[v]<d[k]+edge[i].len){ 28 d[v]=d[k]+edge[i].len; 29 if (++sum[v]>n)return 0; 30 if (!vis[v]){ 31 vis[v]=1; 32 q.push(v); 33 } 34 } 35 } 36 } 37 return 1; 38 } 39 int main(){ 40 scanf("%d%d",&n,&m); 41 memset(head,-1,sizeof(head)); 42 for(int i=1;i<=m;i++){ 43 scanf("%d%d%d",&p,&x,&y); 44 if ((x==y)&&(p&1))continue; 45 if (x==y){ 46 printf("-1"); 47 return 0; 48 } 49 if (p==1){ 50 add(x,y,0); 51 add(y,x,0); 52 } 53 if (p==2)add(x,y,1); 54 if (p==3)add(y,x,0); 55 if (p==4)add(y,x,1); 56 if (p==5)add(x,y,0); 57 } 58 if (!spfa())printf("-1"); 59 else{ 60 for(int i=1;i<=n;i++)ans+=d[i]; 61 printf("%lld",ans); 62 } 63 }