BZOJ 3275.Number -- bipartite graph, minimum cut of network flow

Title Description

There are N positive integers. You need to select some numbers from them to maximize the sum of these numbers.
If two numbers a and B meet the following conditions at the same time, a and B cannot be selected at the same time
1: There is a positive integer C, so that a*a+b*b=c*c
2:gcd(a,b)=1
n≤3000

Problem solution

We can easily O ( n 2 log ⁡ a ) O(n^2\log a) Which numbers can not be selected at the same time in the time of O(n2loga). Then follow the routine and solve this problem with network flow.

We can first assume that all numbers are selected, and then use the minimum cut to find the minimum sum of the numbers to be removed.

However, the limitation of the topic is very strange. It is not the form of "a selects b must be selected", but "a selects b cannot be selected". Therefore, our graph cannot be simply defined as the unified form of "the point connected with S indicates that it is selected, and the point connected with T indicates that it is not selected".

This question reminds me of another question, which is also the limitation of "a chooses b can'T choose". Because the restricted connected edges form a grid graph, the points can be colored in black and white, that is, some points are defined as "connected with S means selected, connected with T means not selected", and the other part is "connected with S means not selected, and connected with T means selected". In this way, the definitions of points connected with edges (limiting conditions) must be different, which is transformed into "a selected, b must be selected" Limitations.

The essence of this technique is to divide the points into a bipartite graph, and there are no edges between the same half of the points. Can this technique be used in this problem?

We found that the side of this question is very special. It is required that the two numbers are the simplest, and the number of stocks can not be selected at the same time. In fact, the number of hook shares is very rare. It is found that a number seems to be the most and a different number is the simplest number of hook shares, so there will be no ring. Acyclic graphs can be transformed into bipartite graphs.

Then the problem is finished. I seldom do the problem of network flow, so I'm not very good at analyzing this metaphysical complexity. Anyway, Dinic just goes through it casually.

code

#include<cstdio>//JZM yyds!!
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<ctime>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define ll long long
#define uns unsigned
#define MOD 
#define MAXN 100005
#define INF 1e17
#define IF (it->first)
#define IS (it->second)
using namespace std;
inline ll read(){
	ll x=0;bool f=1;char s=getchar();
	while((s<'0'||s>'9')&&s>0)f^=(s=='-'),s=getchar();
	while(s>='0'&&s<='9')x=(x<<1)+(x<<3)+(s^48),s=getchar();
	return f?x:-x;
}
int pt[30],lp;
inline void print(ll x,char c='\n'){
	if(x<0)putchar('-'),x=-x;
	pt[lp=1]=x%10;
	while(x>9)x/=10,pt[++lp]=x%10;
	while(lp)putchar(pt[lp--]^48);
	putchar(c);
}
inline ll lowbit(ll x){return x&-x;}

struct edge{
	int v,to;ll f;edge(){}
	edge(int V,ll F,int T){v=V,f=F,to=T;}
}e[1000005];
int EN=1,G[MAXN],ps;
inline void addedge(int u,int v,ll f){
	e[++EN]=edge(v,f,G[u]),G[u]=EN;
	e[++EN]=edge(u,0,G[v]),G[v]=EN;
}
int cur[MAXN],ds[MAXN];
queue<int>q;
inline bool dcbfs(int S,int T){
	for(int i=1;i<=ps;i++)ds[i]=-1;
	while(!q.empty())q.pop();
	q.push(S),ds[S]=0;
	while(!q.empty()){
		int u=q.front();q.pop();
		if(u==T)continue;
		for(int i=G[u];i;i=e[i].to){
			int v=e[i].v;
			if(e[i].f>0&&ds[v]<0)ds[v]=ds[u]+1,q.push(v);
		}
	}return ds[T]>=0;
}
inline ll dcdfs(int x,int T,ll lim){
	if(x==T)return lim;
	ll res=lim;
	for(int i=cur[x];i&&res;i=e[i].to){
		cur[x]=i;
		int v=e[i].v;
		if(ds[v]==ds[x]+1&&e[i].f>0){
			ll ad=dcdfs(v,T,min(e[i].f,res));
			e[i].f-=ad,res-=ad,e[i^1].f+=ad;
		}
	}return lim-res;
}
inline ll dinic(int S,int T){
	ll res=0;
	while(dcbfs(S,T)){
		for(int i=1;i<=ps;i++)cur[i]=G[i];
		while(ll ad=dcdfs(S,T,INF))res+=ad;
	}return res;
}

inline ll gcd(ll a,ll b){return !b?a:gcd(b,a%b);}
int n,m,S,T,a[MAXN],cl[MAXN];
bool vis[MAXN];
vector<int>D[MAXN];
inline bool check(ll a,ll b){
	ll c=a*a+b*b,qc=sqrt(c);
	return gcd(a,b)==1&&qc*qc==c;
}
bool ok=1;
inline void dfs(int x,int c){
	cl[x]=c,vis[x]=1;
	for(auto v:D[x]){
		if(!vis[v])dfs(v,c^1);
		else if(cl[v]==cl[x])ok=0;
	}
}
ll sum;
signed main()
{
	n=read();
	for(int i=1;i<=n;i++)a[i]=read(),sum+=a[i];
	for(int i=1;i<n;i++)
		for(int j=i+1;j<=n;j++)
			if(check(a[i],a[j]))
				D[i].push_back(j),D[j].push_back(i);
	for(int i=1;i<=n;i++)if(!vis[i])dfs(i,2);
	ps=n,S=++ps,T=++ps;
	for(int i=1;i<=n;i++){
		if(cl[i]==2){
			addedge(S,i,a[i]);
			for(auto v:D[i])addedge(i,v,INF);
		}else addedge(i,T,a[i]);
	}
	printf("%lld\n",sum-dinic(S,T));
	return 0;
}

Tags: Algorithm network-flows

Posted on Sat, 06 Nov 2021 10:42:30 -0400 by Vasudhevan