zoukankan      html  css  js  c++  java
  • bzoj3158&3275: 千钧一发(最小割)

    3158: 千钧一发

    题目:传送门

    题解:

       这是一道很好的题啊...极力推荐

       细看题目:要求一个最大价值,那么我们可以转换成求损失的价值最小

       那很明显就是最小割的经典题目啊?!

       但是这里两个子集的分化并不明显...GG

       耐心一点,从题目的要求再入手:

       对于第二个要求,如果两点的a值都为偶数,那么肯定满足

       那如果两个数都为奇数的话,也必定满足要求一,证明如下:

       1、一个奇数的平方%4为1,一个偶数的平方%4为0

       2、两个奇数的平方和%4为2

       3、如果两个奇数的平方和是一个奇数的平方,那么%4应该为1,不符合

       4、如果两个奇数的平方和是一个偶数的平方,那么%4应该为0,不符合

       因此得证。

       这样子思考的话,两个子集的分化就较为明显了:

       st向a值为奇数的相连,a值为偶数的向ed相连,容量都为b值;这样子所形成的两个子集里面的点一定都是符合要求的。

       最后一步,也是最关键的一步:

       两个子集之间两两匹配,如果当前匹配的两个点是不符合要求的,就将这两个点相连,容量为无限大。

       有什么用呢?自己画几个图便很容易理解:

       这时候我们跑最小割的话,割出来的边就是损失价值的最小值

       用sum-最小割就是答案啊

    代码:

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<cstdlib>
      4 #include<cmath>
      5 #include<algorithm>
      6 #define qread(x) x=read()
      7 using namespace std;
      8 typedef long long LL;
      9 const LL inf=999999999;
     10 LL n,st,ed,sum;
     11 LL A[1100],B[1100];
     12 inline LL read()
     13 {
     14     LL f=1,x=0;char ch;
     15     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     16     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
     17     return f*x;
     18 }
     19 struct node
     20 {
     21     LL x,y,c,next,other;
     22 }a[2100000];LL len,last[110000];
     23 void ins(LL x,LL y,LL c)
     24 {
     25     int k1,k2;
     26     k1=++len;
     27     a[len].x=x;a[len].y=y;a[len].c=c;
     28     a[len].next=last[x];last[x]=len;
     29     
     30     k2=++len;
     31     a[len].x=y;a[len].y=x;a[len].c=0;
     32     a[len].next=last[y];last[y]=len;
     33     
     34     a[k1].other=k2;
     35     a[k2].other=k1;
     36 }
     37 LL list[11000],h[11000],head,tail;
     38 bool bt_h()
     39 {
     40     memset(h,0,sizeof(h));h[st]=1;
     41     list[1]=st;head=1;tail=2;
     42     while(head!=tail)
     43     {
     44         int x=list[head];
     45         for(int k=last[x];k;k=a[k].next)
     46         {
     47             int y=a[k].y;
     48             if(h[y]==0 && a[k].c)
     49             {
     50                 h[y]=h[x]+1;
     51                 list[tail++]=y;
     52             }
     53         }
     54         head++;
     55     }
     56     if(h[ed])return true;
     57     return false;
     58 }
     59 LL find_flow(LL x,LL flow)
     60 {
     61     if(x==ed)return flow;
     62     LL s=0,t;
     63     for(int k=last[x];k;k=a[k].next)
     64     {
     65         int y=a[k].y;
     66         if(h[y]==h[x]+1 && a[k].c>0 && flow>s)
     67         {
     68             s+=t=find_flow(y,min(a[k].c,flow-s));
     69             a[k].c-=t;a[a[k].other].c+=t;
     70         }
     71     }
     72     if(s==0)h[x]=0;
     73     return s;
     74 }
     75 LL gcd(LL a,LL b)
     76 {
     77     return a==0?b:gcd(b%a,a);
     78 }
     79 bool pd(LL x,LL y)
     80 {
     81     LL T=x*x+y*y,t=sqrt(T);
     82     if(t*t!=T)return true;
     83     if(gcd(x,y)>1)return true;
     84     return false;
     85 }
     86 int main()
     87 {
     88     sum=0;
     89     qread(n);
     90     len=0;memset(last,0,sizeof(last));
     91     for(int i=1;i<=n;i++)qread(A[i]);
     92     for(int i=1;i<=n;i++){qread(B[i]);sum+=B[i];}
     93     st=n+1;ed=st+1;
     94     for(int i=1;i<=n;i++)
     95     {
     96         if(A[i]%2==1)ins(st,i,B[i]);
     97         else ins(i,ed,B[i]);
     98     }
     99     for(int i=1;i<=n;i++)
    100         for(int j=1;j<=n;j++)
    101             if((A[i]%2==1) && (A[j]%2==0) && !pd(A[i],A[j]))
    102                 ins(i,j,inf);
    103     LL ans=0;
    104     while(bt_h())ans+=find_flow(st,inf);
    105     printf("%lld
    ",sum-ans);
    106     return 0;
    107 }
  • 相关阅读:
    CodeForces
    bzoj 2257: [Jsoi2009]瓶子和燃料
    【NOIP2009】Hankson 的趣味题
    51Nod 1203 JZPLCM
    bzoj 3751: [NOIP2014]解方程
    UOJ #11. 【UTR #1】ydc的大树
    Tenka1 Programmer Contest D
    bzoj 5000: OI树
    bzoj 1407: [Noi2002]Savage
    bzoj 3551: [ONTAK2010]Peaks加强版
  • 原文地址:https://www.cnblogs.com/CHerish_OI/p/8428568.html
Copyright © 2011-2022 走看看