[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 } 
View Code

 

posted @ 2019-11-10 17:34  PYWBKTDA  阅读(132)  评论(0编辑  收藏  举报