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 }

     

     

  • 相关阅读:
    logstash定义表达式
    redis
    HTTP 错误 500.19 请求的页面的相关配置数据无效 解决办法
    redis sentinel集群
    Elasticsearch6.0及其head插件安装
    Elasticsearch5.2.0部署过程的坑
    Centos7远程桌面 vnc/vnc-server的设置
    python-day27--configparser模块
    python-day27--hashlib模块-摘要算法
    python-day21--os模块
  • 原文地址:https://www.cnblogs.com/myx12345/p/9264948.html
Copyright © 2011-2022 走看看