P2765 魔术球问题

每个数可以放在和它和是平方的数上面

我们可以想到,如果一个点可以放在某个点上面是那个点向它连边

如果一个点向它所有能连的点连边,那么它的最小链覆盖就是我们要找的答案

经过简单推理可以发现,每个点可以连接的点的大小是递增的,那么把编号小的点放在柱子下面一定更优

这样连边就行了

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<vector>
#include<cctype>
#include<cstring>
using namespace std;
#define rg register
inline int read(){
	rg char ch=getchar();
	rg int x=0,f=0;
	while(!isdigit(ch)) f|=(ch=='-'),ch=getchar();
	while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return f?-x:x;
}
int n;
const int N=5005,M=12005<<2;
int head[N],ver[M],nxt[M],flow[M],tot=1;
int dis[N],cur[N];
inline void add(int x,int y,int z){
	ver[++tot]=y;
	flow[tot]=z;
	nxt[tot]=head[x];
	head[x]=tot;
}
inline void adds(int x,int y,int z){
	add(x,y,z);
	add(y,x,0);
}
int s,t;
inline int bfs(){
	queue<int> q;
	q.push(s);
	memset(dis,0,sizeof dis);
	dis[s]=1;
	while(!q.empty()){
		int x=q.front();q.pop();
		cur[x]=head[x];
		for(int y,i=head[x];i;i=nxt[i]){
			y=ver[i];
			if(!dis[y]&&flow[i]){
				dis[y]=dis[x]+1;
				q.push(y);
			}
		}
	}
	return dis[t];
}
int dfs(int x,int f){
	if(x==t) return f;
	int used=0;
	for(int y,w,&i=cur[x];i;i=nxt[i]){
		y=ver[i];
		if(dis[y]==dis[x]+1&&flow[i]){
			w=dfs(y,min(f-used,flow[i]));
			if(w){
				flow[i]-=w;
				flow[i^1]+=w;
				used+=w;
				if(used==f) return f;
			}
		}
	}
	if(!used) dis[x]=0;
	return used;
}
inline int dinic(){
	int ans=0;
	while(bfs()) ans+=dfs(s,0x3f3f3f3f);
	return ans;
}
int vis[N];
int base=2500;
void work(int x){
	vis[x]=1;
	printf("%d ",x);
	for(int i=head[x];i;i=nxt[i]){
		if(i&1||flow[i]) continue;
		work(ver[i]-base);
	}
}
signed main(){
	n=read();
	int now=0;
	s=0;t=5004;
	adds(s,1,1);
	adds(1+base,t,1);
	for(int i=2;;++i){
		adds(s,i,1);
		adds(i+base,t,1);
		for(int j=1;j*j<i+i;++j){
			if(j*j<=i) continue;
			adds(j*j-i,i+base,1);
			//cout<<j*j-i<<" link "<<i<<endl;
		}
		now+=dinic();
		//cout<<i<<" "<<now<<endl;
		if(i-now<=n) continue;
		printf("%d\n",i-1);
		for(int j=1;j<i;++j) if(!vis[j]) work(j),puts("");
		break;
	}
	return 0;
}
posted @ 2020-06-12 21:55  __int256  阅读(145)  评论(0编辑  收藏  举报