3158: 千钧一发
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 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 }