bzoj 4514: 数字配对

题目大意

自己看

题解

我们打表观察规律发现一定能构成一张二分图
也就是不存在奇环
所以我们一般保证费用非负的最大流即可.

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
template<typename T>inline void read(T &x){
	x=0;char ch;bool flag = false;
	while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
	while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
inline int cat_max(const int &a,const int &b){return a>b ? a:b;}
inline int cat_min(const int &a,const int &b){return a<b ? a:b;}
const int maxn = 256;
const int inf = 0x3f3f3f3f;
inline bool judge(int n){
	if(n == 1) return false;
	if(n == 2) return true;
	for(int i = 2;i*i<=n;++i){
		if(n % i == 0) return false;
	}return true;
}
int a[maxn],b[maxn];ll c[maxn];
namespace gra{
	struct Edge{
		int to,next;
	}G[21010];
	int head[maxn],cnt;
	void add(int u,int v){
		//printf("%d\n",cnt);
		G[++cnt].to = v;
		G[cnt].next = head[u];
		head[u] = cnt;
	}
	inline void insert(int u,int v){
		add(u,v);add(v,u);
	}
	int col[maxn];
#define v G[i].to
	void dfs(int u,int c){
		col[u] = c;
		for(int i = head[u];i;i=G[i].next){
			if(col[v] == -1) dfs(v,c^1);
		}
	}
#undef v
}
namespace net{
	struct Edge{
		int to,next,cap;
		ll cost;
	}G[21010];
	int head[maxn],cnt=1;
	void add(int u,int v,int c,ll co){
		//printf("%d\n",cnt);
		G[++cnt].to = v;
		G[cnt].next = head[u];
		head[u] = cnt;
		G[cnt].cap = c;
		G[cnt].cost = co;
	}
	inline void insert(int u,int v,int c,ll co){
		//printf("%d -> %d (%d,%lld)\n",u,v,c,co);
		add(u,v,c,co);add(v,u,0,-co);
	}
	const int lim = maxn<<2;
	int S = maxn-5,T = S+1,l,r,q[lim+10];
	int flow[maxn],p[maxn];
	ll dis[maxn],nw_dis;
	int ans;
	bool inq[maxn];
	inline int find(int r,ll w){
		int l = 0,ret = 0;
		while(l <= r){
			int mid = l+r >> 1;
			if(mid*w+nw_dis >= 0) ret = mid,l = mid+1;
			else r = mid-1;
		}return ret;
	}
#define v G[i].to
	bool spfa(){
		memset(dis,-0x3f,sizeof dis);
		l = 0;r = -1;q[++r] = S;
		dis[S] = 0;flow[S] = inf;
		inq[S] = true;
		while(l <= r){
			int u = q[l % lim];++l;
			for(int i = head[u];i;i=G[i].next){
				if(dis[v] < dis[u] + G[i].cost && G[i].cap){
					dis[v] = dis[u] + G[i].cost;
					flow[v] = min(flow[u],G[i].cap);
					p[v] = i;
					if(!inq[v]){
						q[++r % lim] = v;
						inq[v] = true;
					}
				}
			}inq[u] = false;
		}if(dis[T] == dis[0]) return false;
		if(dis[T] < 0) flow[T] = find(flow[T],dis[T]);
		if(flow[T] == 0) return false;
		ans += flow[T];
		nw_dis += flow[T]*dis[T];
		for(int u = T;u != S;u = G[p[u]^1].to)
			G[p[u]].cap -= flow[T],G[p[u]^1].cap += flow[T];
		return true;
	}
#undef v
}
int main(){
	int n;read(n);memset(gra::col,-1,sizeof gra::col);
	for(int i=1;i<=n;++i) read(a[i]);
	for(int i=1;i<=n;++i) read(b[i]);
	for(int i=1;i<=n;++i) read(c[i]);
	for(int i=1;i<=n;++i){
		for(int j=1;j<=n;++j){
			if(i == j) continue;
			if(a[i] % a[j] == 0 && judge(a[i]/a[j])){
				gra::insert(i,j);
			}
		}
	}
	for(int i=1;i<=n;++i) if(gra::col[i] == -1) gra::dfs(i,0);
	for(int u=1;u<=n;++u){
		if(gra::col[u] == 0){
			net::insert(net::S,u,b[u],0);
			for(int i = gra::head[u];i;i=gra::G[i].next){
				net::insert(u,gra::G[i].to,inf,c[u]*c[gra::G[i].to]);
			}
		}else{
			net::insert(u,net::T,b[u],0);
		}
	}while(net::spfa());
	printf("%d\n",net::ans);
	getchar();getchar();
	return 0;
}
posted @ 2017-02-17 18:01  Sky_miner  阅读(250)  评论(0编辑  收藏  举报