zoukankan      html  css  js  c++  java
  • 网络流24题 魔术球问题

    题目传送门

    又是一个神奇的建图题,建图(Van)♂全不会啊

    大体就是我们一个一个的把球放进来,每放进来一个,我们就求出当前的最小路径覆盖数(当前顶点数-最大流),直到最小路径覆盖数({>})柱子数。此时的球的编号(-1)就是第一问的答案。第二问就是求每一条路径,顺着推下来就好了

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #include<cmath>
    using namespace std;
    struct zzz{
    	int t,len,nex;
    }e[100010<<1]; int head[20010],tot=1;
    void add(int x,int y,int z){
    	e[++tot].t=y;
    	e[tot].len=z;
    	e[tot].nex=head[x];
    	head[x]=tot;
    }
    int s=0,t=20000,vis[20010],pre[20010];
    bool bfs(){
    	memset(vis,0,sizeof(vis));
    	queue <int> q; q.push(s); vis[s]=1;
    	while(!q.empty()){
    		int k=q.front(); q.pop();
    		for(int i=head[k];i;i=e[i].nex){
    			int to=e[i].t;
    			if(vis[to]||!e[i].len) continue;
    			q.push(to); vis[to]=vis[k]+1;
    			if(to==t) return 1;
    		}
    	}
    	return vis[t];
    }
    int dfs(int now,int flow){
    	if(now==t||!flow) return flow;
    	int rest=0,fl;
    	for(int i=head[now];i;i=e[i].nex){
    		int to=e[i].t;
    		if(vis[to]==vis[now]+1&&(fl=dfs(to,min(flow,e[i].len)))){
    			e[i].len-=fl, e[i^1].len+=fl, rest+=fl;
    			if(rest==flow) return rest;
    		}
    	}
    	if(rest<flow) vis[now]=0;
    	return rest;
    }
    int dinic(){
    	int ans=0;
    	while(bfs()) ans+=dfs(s,2147483647);
    	return ans;
    }
    int read(){
    	int k=0; char c=getchar();
    	for(;c<'0'||c>'9';) c=getchar();
    	for(;c>='0'&&c<='9';c=getchar())
    	  k=(k<<3)+(k<<1)+c-48;
    	return k;
    }
    bool jl[20010]; int next[20010];
    int main(){
    	int n=read(),cnt=0,num=0;
    	while(cnt<=n){
    		num++; cnt++;
    		for(int i=1;i<num;i++)
    		  if(sqrt(i+num)==(int)sqrt(i+num))
    			add(i,num+10000,1),add(num+10000,i,0);
    		add(s,num,1); add(num,s,0);
    		add(num+10000,t,1); add(t,num+10000,0);
    		cnt-=dinic();
    	}
    	printf("%d
    ",--num);
    	for(int i=1;i<=num;i++){
    		for(int j=head[i];j;j=e[j].nex){
    			if(!e[j].len){
    				next[i]=e[j].t-10000;
    				break;
    			}
    		}
    	}
    	for(int i=1;i<=num;i++){
    		if(jl[i]) continue;
    		int x=i;
    		while(x!=-10000){
    			jl[x]=1; printf("%d ",x);
    			x=next[x];
    		}
    		printf("
    ");
    	}
    	return 0;
    }
    
  • 相关阅读:
    初学者bootstrap(五)JavaScript插件(上)在路上(6)
    初学者bootstrap(三)下载与安装在路上(7)
    Viewport响应式 Web 设计在路上(13)
    初学者动画(一)在路上(3)
    svn添加强制注释,precommit结合python
    ftpclient卡死问题
    @Transactional失效的问题
    javamail发送二进制流附件的问题
    springmvc附件上传核心代码
    kafka集群配置与测试
  • 原文地址:https://www.cnblogs.com/morslin/p/11854767.html
Copyright © 2011-2022 走看看