现在的位置: 首页 > 综合 > 正文

【BZOJ】【P3158】【千钧一发】【题解】【最小割】

2017年04月18日 ⁄ 综合 ⁄ 共 1556字 ⁄ 字号 评论关闭

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3158

和3275一样

Code:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1010;
int n;
int a[maxn];
struct edge{  
    int u,v,cap,flow;     
    edge(int _u=0,int _v=0,int _cap=0,int _flow=0):  
        u(_u),v(_v),cap(_cap),flow(_flow){}  
};  
vector<edge>edges;  
vector<int>G[maxn];  
int cur[maxn],vis[maxn];  
void add(int u,int v,int cap){  
    edges.push_back(edge(u,v,cap,0));  
    G[u].push_back(edges.size()-1);  
    edges.push_back(edge(v,u,0,0));   
    G[v].push_back(edges.size()-1);   
}  
int d[maxn],s,t;  
bool bfs(){  
    memset(vis,0,sizeof(vis));  
    queue<int>q;  
    q.push(s);vis[s]=1;  
    while(!q.empty()){  
        int u=q.front();q.pop();  
        for(int i=0;i<G[u].size();i++){  
            edge e=edges[G[u][i]];  
            if(e.cap>e.flow&&!vis[e.v]){  
                d[e.v]=d[u]+1;  
                vis[e.v]=1;  
                q.push(e.v);  
            }  
        }  
    }return vis[t];  
}  
int dfs(int u,int a){  
    int flow=0,f;  
    if(u==t||!a)return a;  
    for(int &i=cur[u];i<G[u].size();i++){  
        edge e=edges[G[u][i]];  
        if(d[e.v]==d[u]+1&&(f=dfs(e.v,min(a,e.cap-e.flow)))>0){  
            edges[G[u][i]].flow+=f;  
            edges[G[u][i]^1].flow-=f;  
            flow+=f;a-=f;  
            if(!a)break;  
        }  
    }return flow;  
}  
int Dinic(){  
    int flow=0;  
    while(bfs()){  
        int x=0;  
        do{  
            flow+=x;  
            memset(cur,0,sizeof(cur));  
        }while(x=dfs(s,INT_MAX));  
    }return flow;  
}  
bool can(int a,int b){
	typedef long long LL;
	LL c=sqrt((LL)a*a+(LL)b*b);
	return !((LL)a*a+(LL)b*b==c*c&&__gcd(a,b)==1);
}
int b[maxn];
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d",&b[i]);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	s=0;t=n+1;
	for(int i=1;i<=n;i++)if(b[i]%2)add(s,i,a[i]);
	for(int i=1;i<=n;i++)if(b[i]%2==0)add(i,t,a[i]);
	for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(b[i]%2&&b[j]%2==0)if(!can(b[i],b[j]))
	add(i,j,INT_MAX);
	cout<<accumulate(a+1,a+1+n,0)-Dinic()<<endl;
	return 0;
}

抱歉!评论已关闭.