zoukankan      html  css  js  c++  java
  • 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
    ",i-1);
    		for(int j=1;j<i;++j) if(!vis[j]) work(j),puts("");
    		break;
    	}
    	return 0;
    }
    
  • 相关阅读:
    线程池的工作原理
    并发处理之master-worker 模式
    Parrot os引导修复
    使用datax mongodb导数据到postgresql数据库遇到访问权限问题
    10、Flink高可用HA
    9、Standalone集群测试运行
    8、Flink Standalone工作流程
    7、Flink Local模式安装部署
    java读取word文档的文字内容
    对文件内容就行修改-java代码
  • 原文地址:https://www.cnblogs.com/XiaoVsun/p/13110662.html
Copyright © 2011-2022 走看看