1. 程式人生 > >bzoj2330: [SCOI2011]糖果 (利用差分約束系統將之轉換成最長路的問題)

bzoj2330: [SCOI2011]糖果 (利用差分約束系統將之轉換成最長路的問題)

問題 時間限制 接下來 show ems 輸入 als include while

題目

技術分享圖片
2330: [SCOI2011]糖果
時間限制: 10 Sec  內存限制: 128 MB
題目描述
幼兒園裏有N個小朋友,lxhgww老師現在想要給這些小朋友們分配糖果,要求每個小朋友都要分到糖果。但是小朋友們也有嫉妒心,總是會提出一些要求,比如小明不希望小紅分到的糖果比他的多,於是在分配糖果的時候,lxhgww需要滿足小朋友們的K個要求。幼兒園的糖果總是有限的,lxhgww想知道他至少需要準備多少個糖果,才能使得每個小朋友都能夠分到糖果,並且滿足小朋友們所有的要求。
輸入
輸入的第一行是兩個整數N,K。
接下來K行,表示這些點需要滿足的關系,每行3個數字,X,A,B。
如果X
=1, 表示第A個小朋友分到的糖果必須和第B個小朋友分到的糖果一樣多; 如果X=2, 表示第A個小朋友分到的糖果必須少於第B個小朋友分到的糖果; 如果X=3, 表示第A個小朋友分到的糖果必須不少於第B個小朋友分到的糖果; 如果X=4, 表示第A個小朋友分到的糖果必須多於第B個小朋友分到的糖果; 如果X=5, 表示第A個小朋友分到的糖果必須不多於第B個小朋友分到的糖果; 輸出 輸出一行,表示lxhgww老師至少需要準備的糖果數,如果不能滿足小朋友們的所有要求,就輸出-1。 樣例輸入 5 7 1 1 2 2 3 2 4 4 1 3 4 5 5 4 5 2 3 5 4 5
1 樣例輸出 11 提示 【數據範圍】 對於30%的數據,保證 N<=100 對於100%的數據,保證 N<=100000 對於所有的數據,保證 K<=1000001<=X<=51<=A, B<=N
View Code

這道題的解法呢正如標題所寫,可以發現小朋友的關系可以構成不等式,所以我們可以把這些條件利用差分約束系統將其轉化為最長路,然後用spfa跑一遍就行了。

附上一個鏈接:

http://wenku.baidu.com/view/c37d3486bceb19e8b8f6baae.html

#include<stdio.h>
#include<string.h>
int h,t,l[101010],dd[500000],ccc[101010],cnt,j,n,m,x,y,xx,hh[101010],w,z;
long long ans;
bool d[101010];
struct node
{
 int next,v,zz;
}b[500000];
void add(int aa,int bb,int cc)
{
 b[++cnt].v=bb;
 b[cnt].next=hh[aa];
 b[cnt].zz=cc;
 hh[aa]=cnt;
}
bool spfa(int q)
{
 int i;
 memset(d,0,sizeof(d));
 h=0,t=0;
 l[q]=0;d[q]=true;
 while(1)
 {
  if(h>t)break;
   
  for(i=hh[q];i!=0;i=b[i].next)
  {
    z=b[i].v;
    w=b[i].zz;
    if(l[q]+w>l[z]){
       l[z]=l[q]+w;
       if(d[z])continue;
       if(++ccc[z]>n)return false;
       dd[++t]=z;
       d[z]=true;
    }   
  }
  d[q]=false;
    q=dd[++h];
 }
 return true;   
}
int main()
{
 int i;
 scanf("%d %d",&n,&m);
 for(i=1;i<=m;i++)
    {
        scanf("%d%d%d",&xx,&x,&y);
        if(xx==1){add(x,y,0);add(y,x,0);}
        else if(xx==2)if(x==y){printf("-1\n");return 0;}else add(x,y,1);
        else if(xx==3)add(y,x,0);
        else if(xx==4)if(x==y){printf("-1\n");return 0;}else add(y,x,1);
        else if(xx==5)add(x,y,0);
    }
 for(i=n;i>=1;i--)
  add(0,i,1);
 if(!spfa(0)){printf("-1\n");return 0;} 
 for(i=1;i<=n;i++)
  ans+=l[i];
 printf("%lld",ans);
  
 return 0;
} 

  

bzoj2330: [SCOI2011]糖果 (利用差分約束系統將之轉換成最長路的問題)