【BZOJ】【3158】千钧一发

时间:2023-03-09 15:02:33
【BZOJ】【3158】千钧一发

网络流/最小割


  这题跟BZOJ 3275限制条件是一样的= =所以可以用相同的方法去做……只要把边的容量从a[i]改成b[i]就行了~

(果然不加当前弧优化要略快一点)

 /**************************************************************
Problem: 3158
User: Tunix
Language: C++
Result: Accepted
Time:196 ms
Memory:13028 kb
****************************************************************/ //BZOJ 3158
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
#define pb push_back
using namespace std;
inline int getint(){
int v=,sign=; char ch=getchar();
while(ch<''||ch>''){ if (ch=='-') sign=-; ch=getchar();}
while(ch>=''&&ch<=''){ v=v*+ch-''; ch=getchar();}
return v*sign;
}
const int N=,M=,INF=~0u>>;
typedef long long LL;
/******************tamplate*********************/
int n,m,tot,ans,a[N],b[N];
struct edge{int to,v;};
int gcd(int a,int b){return b ? gcd(b,a%b) : a;}
bool judge(LL a,LL b){
LL s=a*a+b*b;
LL q=sqrt(s);
if (q*q!=s) return ;
if (gcd(a,b)!=) return ;
return ;
}
struct Net{
edge E[M];
int head[N],next[M],cnt;
void ins(int x,int y,int v){
E[++cnt]=(edge){y,v};
next[cnt]=head[x]; head[x]=cnt;
}
void add(int x,int y,int v){
ins(x,y,v); ins(y,x,);
}
int s,t,d[N],Q[N];
void init(){
n=getint(); cnt=;
tot=ans=;
s=; t=n+;
F(i,,n) a[i]=getint();
F(i,,n){
b[i]=getint();tot+=b[i];
if (a[i]&) add(s,i,b[i]);
else add(i,t,b[i]);
}
F(i,,n) if (a[i]&)
F(j,,n) if((a[j]&)==)
if (judge(a[i],a[j])) add(i,j,INF);
}
bool mklevel(){
memset(d,-,sizeof d);
d[s]=;
int l=,r=-;
Q[++r]=s;
while(l<=r){
int x=Q[l++];
for(int i=head[x];i;i=next[i])
if (d[E[i].to]==- && E[i].v){
d[E[i].to]=d[x]+;
Q[++r]=E[i].to;
}
}
return d[t]!=-;
}
int dfs(int x,int a){
if (x==t) return a;
int flow=;
for(int i=head[x];i && flow<a;i=next[i])
if (E[i].v && d[E[i].to]==d[x]+){
int f=dfs(E[i].to,min(a-flow,E[i].v));
E[i].v-=f;
E[i^].v+=f;
flow+=f;
}
if (!flow) d[x]=-;
return flow;
}
void Dinic(){
while(mklevel())
ans+=dfs(s,INF);
}
}G1; int main(){
#ifndef ONLINE_JUDGE
freopen("3158.in","r",stdin);
freopen("3158.out","w",stdout);
#endif
G1.init(); G1.Dinic();
printf("%d\n",tot-ans);
return ;
}

3158: 千钧一发

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 590  Solved: 225
[Submit][Status][Discuss]

Description

 【BZOJ】【3158】千钧一发

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

[Submit][Status][Discuss]