[SCOI2011]糖果

题目传送门

对于一个刚接触差分约束系统的OIer来说,这算是一道细节比较多,也比较难的题。首先就是这道题有5种不同的约束条件,对于条件1,3,5直接按照差分条件建边即可,条件2,4要先移项,再建边。之后再求单源最长路,好不容易做出来后你就会发现数据卡SPFA!!!!这里可以加两个小小的优化:1)当a,b严格大于或小于时,他们不能为同一个人,先预判出来可以节省大量时间(不加#5会TLE)。还有要倒序建边,,,(没有任何道理,倒序就能AC,正序会TLE)

参考程序如下:

  1 #include<iostream>
  2 #include<cstring>
  3 #include<queue>
  4 #include<cstdio>
  5 using namespace std;
  6 long long n,m,dist[350005],v[350005],w[350005],nxt[350005],head[350005],cnt,x,a,b,ring[350005];
  7 bool vis[350005];
  8 inline int read()
  9 {
 10     int f=1,x=0;
 11     char s=getchar();
 12     while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
 13     while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
 14     return x*f;
 15 }
 16 inline void add(int a,int b,int c)
 17 {
 18     v[++cnt]=b;
 19     w[cnt]=c;
 20     nxt[cnt]=head[a];
 21     head[a]=cnt;
 22 }
 23 inline bool spfa(int node)
 24 {
 25     queue<int>q;
 26     q.push(node);
 27     vis[node]=1;
 28     while(!q.empty())
 29     {
 30         int c=q.front();
 31         q.pop();
 32         vis[c]=0;
 33         ring[c]++;
 34         //cout<<c<<endl;
 35         if(ring[c]==n)return 0;
 36         for(int i=head[c];i;i=nxt[i])
 37         {
 38             int y=v[i];
 39             //cout<<"-------------------CJXGBH---------------------"<<endl;
 40             //cout<<dist[y]<<" "<<dist[c]<<" "<<w[i]<<endl;
 41             if(dist[y]<dist[c]+w[i])
 42             {
 43                 dist[y]=dist[c]+w[i];
 44                 if(!vis[y])
 45                 {
 46                     q.push(y);
 47                     vis[y]=1;
 48                 }
 49             }
 50         }
 51     }
 52     return 1;
 53 }
 54 int main()
 55 {
 56     //freopen("1.in","r",stdin);
 57     n=read();m=read();
 58     for(int i=1;i<=m;i++)
 59     {
 60         x=read();a=read();b=read();
 61         if(x==1)
 62         {
 63             add(a,b,0);
 64             add(b,a,0);    
 65         }
 66         if(x==2)
 67         {
 68             add(a,b,1);
 69             if(a==b)
 70             {
 71                 cout<<"-1";
 72                 return 0;
 73             }
 74         }    
 75         if(x==3)
 76         {
 77             add(b,a,0);
 78         }
 79         if(x==4)
 80         {
 81             add(b,a,1); 
 82             if(a==b)
 83             {
 84                 cout<<"-1";
 85                 return 0;
 86             }       
 87         }
 88         if(x==5)
 89         {
 90             add(a,b,0);
 91         }
 92     }
 93     for(int i=n;i>=1;i--)
 94     {
 95         add(0,i,1);
 96     }
 97     if(!spfa(0))
 98     {
 99         cout<<"-1";
100         return 0;    
101     }
102     long long ans=0;
103     for(int i=1;i<=n;i++)ans+=dist[i];
104     cout<<ans; 
105     return 0;
106 }
View Code
原文地址:https://www.cnblogs.com/szmssf/p/11079874.html