zoukankan      html  css  js  c++  java
  • 【BZOJ2330】糖果(差分约束系统,强连通分量,拓扑排序)

    题意:

    幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果。但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候,lxhgww需要满足小朋友们的K个要求。幼儿园的糖果总是有限的,lxhgww想知道他至少需要准备多少个糖果,才能使得每个小朋友都能够分到糖果,并且满足小朋友们所有的要求。

    输入的第一行是两个整数NK

    接下来K行,表示这些点需要满足的关系,每行3个数字,XAB

    如果X=1, 表示第A个小朋友分到的糖果必须和第B个小朋友分到的糖果一样多;

    如果X=2, 表示第A个小朋友分到的糖果必须少于第B个小朋友分到的糖果;

    如果X=3, 表示第A个小朋友分到的糖果必须不少于第B个小朋友分到的糖果;

    如果X=4, 表示第A个小朋友分到的糖果必须多于第B个小朋友分到的糖果;

    如果X=5, 表示第A个小朋友分到的糖果必须不多于第B个小朋友分到的糖果;

    对于所有的数据,保证 N<=100000,K<=100000,1<=X<=5,1<=A, B<=N

    思路:第一反应应该是差分约束系统,但N的范围令人不放心,实际上裸SPFA也需要一些优化才能跑过去

    知乎上有几位大佬说这题是tarjan缩点+拓扑排序,确实这种做法理论复杂度才是有保证的

    先建立原图,对于等于关系连双向边,小于等于(和大于等于,显然等价)连单向边,先缩一次点,同一个分量里的人糖果数一定相等

    再进行拓扑排序计算每一个分量的糖果数,环会导致无解,注意糖果数和前面推导不同时需要取MAX

    最后特判下同一个分量里的边有没有不等的,有则无解

    SPFA

     1 var q:array[0..2000000]of longint;
     2     head,vet,next,len,dis,time:array[1..200000]of longint;
     3     inq:array[1..200000]of boolean;
     4     n,m,i,x,a,b,tot:longint;
     5     ans,tmp:int64;
     6  
     7 procedure add(a,b,c:longint);
     8 begin
     9  inc(tot);
    10  next[tot]:=head[a];
    11  vet[tot]:=b;
    12  len[tot]:=c;
    13  head[a]:=tot;
    14 end;
    15  
    16 procedure spfa;
    17 var t,w,i,u,e,v:longint;
    18 begin
    19  fillchar(time,sizeof(time),0);
    20  t:=0; w:=-1;
    21  for i:=1 to n do
    22  begin
    23   dis[i]:=1; inc(w); q[w]:=i; inq[i]:=true;
    24  end;
    25  
    26  while t<=w do
    27  begin
    28   u:=q[t mod n]; inc(t); inq[u]:=false;
    29   e:=head[u];
    30   while e<>0 do
    31   begin
    32    v:=vet[e];
    33    if dis[u]+len[e]>dis[v] then
    34    begin
    35     dis[v]:=dis[u]+len[e];
    36     if not inq[v] then
    37     begin
    38      inc(time[v]);
    39      if time[v]>n then
    40      begin
    41       writeln(-1); ans:=-1;
    42       exit;
    43      end;
    44      inc(w); q[w mod n]:=v; inq[v]:=true;
    45     end;
    46    end;
    47    e:=next[e];
    48   end;
    49  end;
    50 end;
    51  
    52 begin
    53   
    54  read(n,m);
    55  for i:=1 to m do
    56  begin
    57   read(x,a,b);
    58   if (x and 1=0)and(a=b) then
    59   begin
    60    writeln(-1);
    61    exit;
    62   end;
    63   case x of
    64    1:begin add(b,a,0); add(a,b,0); end;
    65    2:add(a,b,1);
    66    3:add(b,a,0);
    67    4:add(b,a,1);
    68    5:add(a,b,0);
    69   end;
    70  end;
    71  spfa;
    72  if ans=0 then
    73  begin
    74   for i:=1 to n do ans:=ans+dis[i];
    75  
    76   writeln(ans);
    77  end;
    78   
    79 end.

    tarjan+拓扑排序

      1 #include<map> 
      2 #include<set>
      3 #include<cmath>
      4 #include<cstdio>
      5 #include<vector>
      6 #include<cstring>
      7 #include<cstdlib>
      8 #include<iostream>
      9 #include<algorithm>
     10 #include<queue>
     11 using namespace std;
     12 const int M=210000;
     13 int head[M],vet[M],next[M],len[M],a[M],b[M],c[M],dfn[M],low[M],flag[M],ind[M],stack[M],s[M];
     14 int n,m,i,tot,id,top,cnt;
     15 long long d[M],size[M];
     16  
     17 void add(int a,int b,int c)
     18 {
     19   next[++tot]=head[a];
     20   vet[tot]=b;
     21   len[tot]=c;
     22   head[a]=tot;
     23   ind[b]++;
     24 }
     25  
     26 void swap(int &a,int &b)
     27 {
     28     int t;
     29     t=a;a=b;b=t;
     30 }
     31  
     32 void dfs(int u)
     33 {
     34     int e,v;
     35     flag[u]=1;
     36     stack[++top]=u;
     37     dfn[u]=low[u]=++cnt;
     38     for(e=head[u];e;e=next[e])
     39     {
     40         v=vet[e];
     41         if(!flag[v])
     42         {
     43             dfs(v);
     44             low[u]=min(low[u],low[v]);
     45         }
     46          else if(!s[v]) low[u]=min(low[u],low[v]);
     47     }
     48     if(low[u]==dfn[u])
     49     {
     50         id++; 
     51         while(stack[top]!=u)
     52         {
     53             s[stack[top]]=id; 
     54             size[id]++;
     55             top--;
     56         }
     57         s[stack[top]]=id; 
     58         size[id]++;
     59         top--;
     60     }
     61      
     62 }
     63  
     64 long long solve()
     65 {
     66     queue<int> q;
     67     int num;
     68     long long sum;
     69     for(int i=1;i<=id;i++)
     70      if(!ind[i]) 
     71      {
     72        q.push(i);
     73        d[i]=1;
     74      } 
     75     if(q.empty()) return -1;
     76     num=0;
     77     while(!q.empty())
     78     {
     79         int u=q.front(); q.pop(); num++;
     80         for(int e=head[u];e;e=next[e])
     81         {
     82             int v=vet[e];
     83             ind[v]--;
     84             d[v]=max(d[v],d[u]+len[e]);
     85             if(!ind[v]) q.push(v);
     86         }
     87     }
     88     if(num<id) return -1;
     89      else 
     90      {
     91         sum=0;
     92         for(int i=1;i<=id;i++) sum=sum+d[i]*size[i];
     93         return sum;
     94      }
     95      
     96 }
     97  
     98 int main()
     99 {
    100    // freopen("bzoj2330.in","r",stdin);
    101    // freopen("bzoj2330.out","w",stdout);
    102     scanf("%d%d",&n,&m);
    103     id=0;
    104     for(i=1;i<=m;i++)
    105     {
    106         scanf("%d%d%d",&a[i],&b[i],&c[i]);
    107         if(a[i]==3||a[i]==4) swap(b[i],c[i]);
    108         if(a[i]==1)
    109         {
    110             add(b[i],c[i],0);
    111             add(c[i],b[i],0);
    112         }
    113         if(a[i]==3||a[i]==5) add(b[i],c[i],0);
    114     }
    115     for(i=1;i<=n;i++)
    116      if(!flag[i]) dfs(i);
    117     //printf("%d
    ",id);
    118     memset(head,0,sizeof(head));
    119     memset(ind,0,sizeof(ind));
    120     tot=0;
    121     for(i=1;i<=m;i++)
    122      if(s[b[i]]!=s[c[i]])
    123      {
    124         if(a[i]==3||a[i]==5) add(s[b[i]],s[c[i]],0); 
    125          else add(s[b[i]],s[c[i]],1); 
    126      }
    127       else
    128       {
    129         if(a[i]==2||a[i]==4) 
    130         {
    131           printf("-1
    ");
    132           return 0;
    133         }   
    134       }
    135  printf("%lld
    ",solve());
    136  return 0;  
    137 }

     

     

  • 相关阅读:
    learning scala view collection
    scala
    learning scala dependency injection
    learning scala implicit class
    learning scala type alise
    learning scala PartialFunction
    learning scala Function Recursive Tail Call
    learning scala Function Composition andThen
    System.Threading.Interlocked.CompareChange使用
    System.Threading.Monitor的使用
  • 原文地址:https://www.cnblogs.com/myx12345/p/9264948.html
Copyright © 2011-2022 走看看