• BZOJ 3158: 千钧一发


    题目

    Time Limit: 10 Sec  Memory Limit: 512 MB
    Submit: 388  Solved: 152
    [Submit][Status]

    Description

     

    Input

    第一行一个正整数N。

    第二行共包括N个正整数,第 个正整数表示Ai。

    第三行共包括N个正整数,第 个正整数表示Bi。

    Output

    共一行,包括一个正整数,表示在合法的选择条件下,可以获得的能量值总和的最大值。

    Sample Input



    4
    3 4 5 12
    9 8 30 9

    Sample Output


    39

    HINT



    1<=N<=1000,1<=Ai,Bi<=10^6

    题解

    这道题目是最小割建图,但是套普通的模型会发现要建出负边来了。所以我们必须反向某些边的定义。由题目我们发现,所有的偶数两两之间一定符合第二条规则,而所有的奇数两两之间一定符合第一条规则,那么二关关系只会建立在奇数和偶数之间了。我们可以考虑反向所有偶数边的定义,在源点到偶数特征值的点之间连一条为当前边价值的边,在奇数特征值和汇点之间连一条为当前边价值的边。然后考虑所有奇数点,从所有奇数点连一条流量为INF的边到和他冲突的偶数点,跑一边最大流就好了!然后用全部的价值和减去最大流结果就是答案。

    代码

      1 /*Author:WNJXYK*/
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<cstring>
      5 #include<iostream>
      6 #include<queue>
      7 using namespace std;
      8 
      9 
     10 inline int remin(int a,int b){return a<b?a:b;}
     11 inline long long sqr(int x){return (long long)x*(long long)x;}
     12 
     13 const int Maxn=1500;
     14 const int Maxm=Maxn*Maxn;
     15 const int inf=2100000000;
     16 struct Edge{
     17     int u,v,f,nxt;
     18     Edge(){}
     19     Edge(int a,int b,int c,int d){
     20         u=a;
     21         v=b;
     22         f=c;
     23         nxt=d;
     24     }
     25 }; 
     26 Edge e[Maxm+10];
     27 int g[Maxn+10];
     28 int cnt=1;
     29 int sink,src;
     30 inline void insertEdge(int u,int v,int f){
     31     cnt++;
     32     e[cnt]=Edge(u,v,f,g[u]);
     33     g[u]=cnt;
     34 }
     35 inline void addEdge(int u,int v,int f){
     36     insertEdge(u,v,f);
     37     insertEdge(v,u,0);
     38 }
     39 
     40 queue<int> que;
     41 int dist[Maxn+10];
     42 
     43 bool spfa(){
     44     while(!que.empty()) que.pop();
     45     memset(dist,-1,sizeof(dist));
     46     dist[src]=0;
     47     que.push(src);
     48     while(!que.empty()){
     49         int now=que.front();
     50         que.pop();
     51         for (int i=g[now];i;i=e[i].nxt){
     52             if (e[i].f!=0 && dist[e[i].v]==-1){
     53                 dist[e[i].v]=dist[now]+1;
     54                 que.push(e[i].v);
     55             }
     56         }
     57     }
     58     return dist[sink]!=-1;
     59 }
     60 
     61 int dfs(int x,int delta){
     62     int ret=0;
     63     if (x==sink){
     64         return delta;
     65     }else{
     66         for (int i=g[x];i;i=e[i].nxt){
     67             if (e[i].f!=0 && dist[e[i].v]==dist[x]+1){
     68                 int ddelta=dfs(e[i].v,remin(e[i].f,delta));
     69                 e[i].f-=ddelta; 
     70                 e[i^1].f+=ddelta; 
     71                 ret+=ddelta; 
     72                 delta-=ddelta;
     73             }
     74         }
     75     }
     76     return ret;
     77 }
     78 
     79 int dinic(){
     80     int ret=0;
     81     while(spfa()){
     82         ret+=dfs(src,inf);
     83     }
     84     return ret;
     85 }
     86 
     87 int n;
     88 int a[1010];
     89 int b[1010];
     90 
     91 inline int gcd(int x,int y)
     92 {
     93      int m=x%y;
     94      while(m!=0)
     95      {
     96           x=y;
     97           y=m;
     98           m=x%y;
     99      }
    100      return y;
    101 } 
    102 
    103 int main(){
    104     //freopen("3158.in","r",stdin);
    105     //freopen("3158.out","w",stdout); 
    106     scanf("%d",&n);
    107     src=0;
    108     sink=n+1;
    109     for (int i=1;i<=n;i++)scanf("%d",&a[i]);
    110     for (int i=1;i<=n;i++)scanf("%d",&b[i]);
    111     long long sum=0;
    112     for (int i=1;i<=n;i++){
    113         if (a[i]%2==0){
    114             addEdge(src,i,b[i]);
    115         }else{
    116             addEdge(i,sink,b[i]);
    117         }
    118         sum+=b[i];
    119     }
    120     for (int i=1;i<=n;i++){
    121         if (a[i]%2==1) continue;
    122         for (int j=1;j<=n;j++){
    123             if (i==j) continue;
    124             if ((a[i]+a[j])%2==0) continue;
    125             if (gcd(a[i],a[j])!=1) continue;
    126             long long tmp=sqr(a[i])+sqr(a[j]);
    127             int tmpk=(int)floor(sqrt(tmp));
    128             if (sqr(tmpk)!=tmp) continue;
    129             addEdge(i,j,inf);
    130         }
    131     }
    132     //printf("%llld
    ",sum);
    133     printf("%lld
    ",sum-dinic());
    134     return 0;
    135 }
    View Code
  • 相关阅读:
    DLinq[新特性]
    破解 iPod Touch[转]
    iPod Touch Online
    谈到Model View Presenter模式之后的随笔[讨论版]
    各家银行买"基金"如何省钱
    WF随笔系列之二 架构、编译、序列化
    JavaScript AppendChild 引发的思考
    IEquatable接口
    DLinq查询
    基金小窍门:如何判断基金的赚与赔
  • 原文地址:https://www.cnblogs.com/WNJXYK/p/4073384.html
Copyright © 2020-2023  润新知