[SCOI2011]糖果
Posted szmssf
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[SCOI2011]糖果相关的知识,希望对你有一定的参考价值。
对于一个刚接触差分约束系统的OIer来说,这算是一道细节比较多,也比较难的题。首先就是这道题有5种不同的约束条件,对于条件1,3,5直接按照差分条件建边即可,条件2,4要先移项,再建边。之后再求单源最长路,好不容易做出来后你就会发现数据卡SPFA!!!!这里可以加两个小小的优化:1)当a,b严格大于或小于时,他们不能为同一个人,先预判出来可以节省大量时间(不加#5会TLE)。还有要倒序建边,,,(没有任何道理,倒序就能AC,正序会TLE)
参考程序如下:
#include<iostream> #include<cstring> #include<queue> #include<cstdio> using namespace std; long long n,m,dist[350005],v[350005],w[350005],nxt[350005],head[350005],cnt,x,a,b,ring[350005]; bool vis[350005]; inline int read() int f=1,x=0; char s=getchar(); while(s<‘0‘||s>‘9‘)if(s==‘-‘)f=-1;s=getchar(); while(s>=‘0‘&&s<=‘9‘)x=x*10+s-‘0‘;s=getchar(); return x*f; inline void add(int a,int b,int c) v[++cnt]=b; w[cnt]=c; nxt[cnt]=head[a]; head[a]=cnt; inline bool spfa(int node) queue<int>q; q.push(node); vis[node]=1; while(!q.empty()) int c=q.front(); q.pop(); vis[c]=0; ring[c]++; //cout<<c<<endl; if(ring[c]==n)return 0; for(int i=head[c];i;i=nxt[i]) int y=v[i]; //cout<<"-------------------CJXGBH---------------------"<<endl; //cout<<dist[y]<<" "<<dist[c]<<" "<<w[i]<<endl; if(dist[y]<dist[c]+w[i]) dist[y]=dist[c]+w[i]; if(!vis[y]) q.push(y); vis[y]=1; return 1; int main() //freopen("1.in","r",stdin); n=read();m=read(); for(int i=1;i<=m;i++) x=read();a=read();b=read(); if(x==1) add(a,b,0); add(b,a,0); if(x==2) add(a,b,1); if(a==b) cout<<"-1"; return 0; if(x==3) add(b,a,0); if(x==4) add(b,a,1); if(a==b) cout<<"-1"; return 0; if(x==5) add(a,b,0); for(int i=n;i>=1;i--) add(0,i,1); if(!spfa(0)) cout<<"-1"; return 0; long long ans=0; for(int i=1;i<=n;i++)ans+=dist[i]; cout<<ans; return 0;
以上是关于[SCOI2011]糖果的主要内容,如果未能解决你的问题,请参考以下文章