码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 3158 千钧一发(最小割)

时间:2015-12-26 15:04:07      阅读:183      评论:0      收藏:0      [点我收藏+]

标签:

 

3158: 千钧一发

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 767  Solved: 290
[Submit][Status][Discuss]

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

Source

 

【思路】

       最小割。

       注意到ai,aj同时是偶数或同时是奇数时必定可以被同时选出:

       1 同为偶数满足条件2

       2 同为奇数时有(2a+1)^2+(2b+1)^2=2(2a^2+2b^2+2a+2b+1),所以满足条件1。

       以此构二分图,设奇数为X结点偶数为Y结点,如果不满足任一条件则连边(Xi,Yj,INF),同时相应连S到X,Y到T的边容量为b,那么答案就是一个二分图最小割,即通过删除一些结点使得满足剩下的结点不相邻且有b之和最小。

 

【代码】

 

  1 #include<cstdio>
  2 #include<cmath>
  3 #include<queue>
  4 #include<cstring>
  5 #include<iostream>
  6 using namespace std;
  7 
  8 typedef long long LL;
  9 const int maxn = 4000+10;
 10 const int INF = 1e9+1e9;
 11 
 12 struct Edge{  int u,v,cap,flow;
 13 }; 
 14 
 15 struct Dinic {
 16     int n,m,s,t;
 17     int d[maxn],cur[maxn],vis[maxn];
 18     vector<int> G[maxn];
 19     vector<Edge> es;
 20     
 21     void init(int n) {
 22         this->n=n;
 23         for(int i=0;i<n;i++) G[i].clear();
 24         es.clear();
 25     }
 26     void AddEdge(int u,int v,int cap) {
 27         es.push_back((Edge){u,v,cap,0});
 28         es.push_back((Edge){v,u,0,0});
 29         m=es.size();
 30         G[u].push_back(m-2);
 31         G[v].push_back(m-1);
 32     }
 33     bool bfs() {
 34         queue<int> q;
 35         memset(vis,0,sizeof(vis));
 36         vis[s]=1; d[s]=0; q.push(s);
 37         while(!q.empty())    {
 38             int u=q.front(); q.pop();
 39             for(int i=0;i<G[u].size();i++) {
 40                 Edge &e=es[G[u][i]];
 41                 int v=e.v;
 42                 if(!vis[v] && e.cap>e.flow) {
 43                     vis[v]=1;
 44                     d[v]=d[u]+1;
 45                     q.push(v);
 46                 }
 47             }
 48         }
 49         return vis[t];
 50     }
 51     int dfs(int u,int a) {
 52         if(u==t || a==0) return a;
 53         int f,flow=0;
 54         for(int& i=cur[u];i<G[u].size();i++) {
 55             Edge& e=es[G[u][i]];
 56             int v=e.v;
 57             if(d[v]==d[u]+1 && (f=dfs(v,min(a,e.cap-e.flow)))>0) {
 58                 e.flow+=f;
 59                 es[G[u][i]^1].flow-=f;
 60                 flow+=f , a-=f;
 61                 if(!a) break;
 62             }
 63         }
 64         return flow;
 65     }
 66     int maxflow(int s,int t) {
 67         this->s=s , this->t=t;
 68         int flow=0;
 69         while(bfs()) {
 70             memset(cur,0,sizeof(cur));
 71             flow+=dfs(s,INF);
 72         }
 73         return flow;
 74     }
 75 } dc;
 76 
 77 int n;
 78 int a[maxn],b[maxn];
 79 
 80 bool issqr(LL x) { return sqrt(x)*sqrt(x) == x;
 81 }
 82 int gcd(int x,int y) {
 83     return y==0? x:gcd(y,x%y);
 84 }
 85 bool jud(LL x,LL y) {
 86     LL t=x*x+y*y , sq=sqrt(t);
 87     if(sq*sq!=t) return 1;
 88     if(gcd(x,y)>1) return 1;
 89     return 0;
 90 }
 91 
 92 int main() {
 93     scanf("%d",&n);
 94     dc.init(n+2);
 95     int s=n,t=s+1;
 96     int ans=0;
 97     for(int i=0;i<n;i++) scanf("%d",&a[i]);
 98     for(int i=0;i<n;i++) scanf("%d",&b[i]) , ans+=b[i];
 99     for(int i=0;i<n;i++)
100         if((a[i]&1)) dc.AddEdge(s,i,b[i]);
101         else dc.AddEdge(i,t,b[i]);
102     for(int i=0;i<n;i++)  for(int j=0;j<n;j++)
103         if((a[i]&1) && (a[j]&1)==0)
104             if(!jud(a[i],a[j]))  dc.AddEdge(i,j,INF);
105     ans-=dc.maxflow(s,t);
106     printf("%d",ans);
107     return 0;
108 }

 

bzoj 3158 千钧一发(最小割)

标签:

原文地址:http://www.cnblogs.com/lidaxin/p/5078060.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!