zoukankan      html  css  js  c++  java
  • 【刷题】LOJ 6003 「网络流 24 题」魔术球

    题目描述

    假设有 (n) 根柱子,现要按下述规则在这 (n) 根柱子中依次放入编号为 (1, 2, 3, 4, cdots) 的球。

    1. 每次只能在某根柱子的最上面放球。

    2. 在同一根柱子中,任何 (2) 个相邻球的编号之和为完全平方数。

    试设计一个算法,计算出在 (n) 根柱子上最多能放多少个球。

    输入格式

    文件第 (1) 行有 (1) 个正整数 (n),表示柱子数。

    输出格式

    第一行是球数。接下来的 (n) 行,每行是一根柱子上的球的编号。

    样例

    样例输入

    4
    

    样例输出

    11
    1 8
    2 7 9
    3 6 10
    4 5 11
    

    数据范围与提示

    (1 leq n leq 55)

    题解

    枚举答案

    对于一个新的数字,它可以新出一根柱子,即直接与源点相连,容量为 (1) ;还可以接在别的数字的后面,即与满足条件的其它数字连边

    当最大流超过 (n) ,就说明需要的柱子超过 (n) 了,枚举的数字的上一个就是答案

    #include<bits/stdc++.h>
    #define ui unsigned int
    #define ll long long
    #define db double
    #define ld long double
    #define ull unsigned long long
    const int MAXN=4100+10,MAXM=300000+10,inf=0x3f3f3f3f;
    int n,ans,e=1,beg[MAXN],nex[MAXM],to[MAXM],cap[MAXM],out[MAXM],pt[MAXN],level[MAXN],cur[MAXN],vis[MAXN],clk,s,t,res;
    std::queue<int> q;
    template<typename T> inline void read(T &x)
    {
    	T data=0,w=1;
    	char ch=0;
    	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    	if(ch=='-')w=-1,ch=getchar();
    	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
    	x=data*w;
    }
    template<typename T> inline void write(T x,char ch='')
    {
    	if(x<0)putchar('-'),x=-x;
    	if(x>9)write(x/10);
    	putchar(x%10+'0');
    	if(ch!='')putchar(ch);
    }
    template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
    template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
    template<typename T> inline T min(T x,T y){return x<y?x:y;}
    template<typename T> inline T max(T x,T y){return x>y?x:y;}
    inline bool check(int x)
    {
    	int qt=std::sqrt(x);
    	return qt*qt==x;
    }
    inline void insert(int x,int y,int z)
    {
    	to[++e]=y;
    	nex[e]=beg[x];
    	out[e]=x;
    	beg[x]=e;
    	cap[e]=z;
    	to[++e]=x;
    	nex[e]=beg[y];
    	out[e]=y;
    	beg[y]=e;
    	cap[e]=0;
    }
    inline bool bfs()
    {
    	memset(level,0,sizeof(level));
    	level[s]=1;
    	q.push(s);
    	while(!q.empty())
    	{
    		int x=q.front();
    		q.pop();
    		for(register int i=beg[x];i;i=nex[i])
    			if(cap[i]&&!level[to[i]])level[to[i]]=level[x]+1,q.push(to[i]);
    	}
    	return level[t];
    }
    inline int dfs(int x,int maxflow)
    {
    	if(x==t||!maxflow)return maxflow;
    	int res=0;
    	vis[x]=clk;
    	for(register int &i=cur[x];i;i=nex[i])
    		if((vis[to[i]]^vis[x])&&cap[i]&&level[to[i]]==level[x]+1)
    		{
    			int f=dfs(to[i],min(maxflow,cap[i]));
    			res+=f;
    			cap[i]-=f;
    			cap[i^1]+=f;
    			maxflow-=f;
    			if(!maxflow)break;
    		}
    	vis[x]=0;
    	return res;
    }
    inline int Dinic()
    {
    	while(bfs())clk++,memcpy(cur,beg,sizeof(cur)),res+=dfs(s,inf);
    	return res;
    }
    inline void dfs(int x)
    {
    	if(!x)return ;
    	vis[x]=1;
    	write(x,' ');
    	dfs(pt[x]);
    }
    int main()
    {
    	read(n);
    	s=3999,t=4000;
    	for(register int i=1;;++i)
    	{
    		insert(s,i,1);insert(i+1600,t,1);
    		for(register int j=1;j<i;++j)
    			if(check(i+j))insert(j,i+1600,1);
    		if(i-Dinic()>n)
    		{
    			ans=i-1;
    			break;
    		}
    	}
    	write(ans,'
    ');
    	for(register int i=2;i<=e;i+=2)
    		if(!cap[i]&&out[i]!=s&&to[i]!=t)pt[out[i]]=to[i]-1600;
    	for(register int i=1;i<=ans;++i)
    		if(!vis[i])dfs(i),puts("");
    	return 0;
    }
    
  • 相关阅读:
    BAT脚本打印空行的使用方法
    Shell脚本关于屏幕输出的字符进行颜色控制的问题
    shell脚本中切换用户执行相应的命令或者shell脚本的方法
    Linux下执行的java命令重定向到文件中的方法
    解决Firefox浏览器每次打开都弹出导入向导的问题
    解决Ruby在IE11中报Unable to get browser (Selenium::WebDriver::Error::NoSuchWindowError)的错误
    6月28日 Django form组件 和 modelform组件
    6月27日 ajax
    6月25日 Django 分页 cookie、session
    6月26日 Django 中间件
  • 原文地址:https://www.cnblogs.com/hongyj/p/9424680.html
Copyright © 2011-2022 走看看