2330: [SCOI2011]糖果

来源:互联网 发布:美国海关数据查询 编辑:程序博客网 时间:2024/05/20 06:53

题目链接](http://www.lydsy.com/JudgeOnline/problem.php?id=2330)

题目大意:给定n个点和之间的大小关系,求每个点最少是多少(必须大于0)

题解:差分约束
(1)A=B,即为a-b>=0&&b-a>=0,add(a,b,0),add(b,a,0)
(2)B>A,即为b-a>=1,add(a,b,1)
(3)A>=B,即为a-b>=0,add(b,a,0)
(4)A>B,即为a-b>=1,add(b,a,1)
(5)A<=B,即为b-a>=0,add(a,b,0)
由于题目中要求每个小朋友都分到糖。新建虚拟源点0,用C表示,即为糖数为0
(6)I>C,即为i-c>=1,add(c,i,1)
具体实现的时候把所有点加入队列,dis设为1就好了

我的收获:第一题

#include <iostream>#include <cstdio>#include <cstring>#include <queue>using namespace std;const int M=100005;int n,k,t;int head[M],d[M],in[M];bool vis[M],flag;queue <int> q;struct edge{int to,nex,val;}e[M*2];void add(int i,int j,int w){e[t].to=j,e[t].nex=head[i],e[t].val=w;head[i]=t++;}bool spfa(){    for(int i=1;i<=n;i++) vis[i]=1,d[i]=1,q.push(i);    while(!q.empty())    {        int u=q.front();q.pop();vis[u]=false;        for(int i=head[u];i!=-1;i=e[i].nex){            int v=e[i].to;            if(d[v]<d[u]+e[i].val){                d[v]=d[u]+e[i].val;                if(++in[v]>n) return false;                if(!vis[v]){                    vis[v]=true;                    q.push(v);                }            }        }    }    return true;}void insert(int p,int x,int y){    if(p==1) add(x,y,0),add(y,x,0);    if(p==2) {add(x,y,1);if(x==y) flag=1;}    if(p==3) add(y,x,0);    if(p==4) {add(y,x,1);if(x==y) flag=1;}    if(p==5) add(x,y,0);}void work(){    if(flag||(!spfa())) {puts("-1");return ;}    long long ans=0;    for(int i=1;i<=n;i++) ans+=d[i];    cout<<ans<<endl;}void init(){    int opt,x,y;    cin>>n>>k;flag=0;    t=0;memset(head,-1,sizeof(head));    while(k--) scanf("%d%d%d",&opt,&x,&y),insert(opt,x,y);}int main(){    init();    work();    return 0;} 
原创粉丝点击