Magic ball problem

Keywords: PHP network

Take the bead as the point, if the condition is satisfied, two sides are connected.

So you can find the maximum number of nodes that can be covered by n paths.

As we all know, minimum edge coverage = total number of points - Maximum Matching

Not here Link

So split the points and run the bipartite chart.

It'S about S to x.

The k-direction x 'continuous edge of a point satisfying the condition

x'connect to T

There are two ways

1. We add points in turn, and run the maximum flow in the residual network every time.

2. We have a two-point answer, running the maximum flow every time.

The former is faster.

QwQ

Output the answer depends on which side of the traffic is full.

/*
@Date    : 2019-07-20 15:12:45
@Author  : Adscn (adscn@qq.com)
@Link    : https://www.cnblogs.com/LLCSBlog
*/
#include<bits/stdc++.h>
using namespace std;
#define IL inline
#define RG register
#define gi getint()
#define gc getchar()
#define File(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
IL int getint()
{
    RG int xi=0;
    RG char ch=gc;
    bool f=0;
    while(ch<'0'||ch>'9')ch=='-'?f=1:f,ch=gc;
    while(ch>='0'&&ch<='9')xi=(xi<<1)+(xi<<3)+ch-48,ch=gc;
    return f?-xi:xi;
}
template<typename T>
IL void pi(T k,char ch=0)
{
    if(k<0)k=-k,putchar('-');
    if(k>=10)pi(k/10,0);
    putchar(k%10+'0');
    if(ch)putchar(ch);
}
const int N=10000;
const int T=30000;
const int S=0;
int sqr[N+7];
struct edge{
    int v,nxt,flow;
}e[200007];
int head[50007],cnt;
int cur[50007];
inline void add(int u,int v,int flow)
{
    e[cnt]=(edge){v,head[u],flow};
    head[u]=cnt++;
}
inline void link(int u,int v,int flow){add(u,v,flow),add(v,u,0);}
int dep[50007];
inline bool bfs(void)
{
    static int Q[50007],l,r;
    memset(dep,0,sizeof dep);
    dep[Q[l=r=0]=S]=1;
    while(l<=r)
    {
        int p=Q[l++];
        for(int i=head[p];~i;i=e[i].nxt)
        {
            int v=e[i].v;
            if(e[i].flow&&dep[v]==0)dep[v]=dep[p]+1,Q[++r]=v;
        }
    }
    return dep[T];
}
inline int dfs(int p,int restflow)
{
    if(p==T||restflow==0)return restflow;
    int sumflow=0;
    for(int &i=cur[p],flow;~i;i=e[i].nxt)
    {
        int v=e[i].v;
        if(e[i].flow&&dep[v]==dep[p]+1&&
            (flow=dfs(v,min(restflow,e[i].flow))))
        {
            restflow-=flow,sumflow+=flow;
            e[i].flow-=flow,e[i^1].flow+=flow;
            if(restflow==0)break;
        }
    }
    return sumflow;
}
inline int dinic()
{
    int maxflow=0;
    while(bfs())
        memcpy(cur,head,sizeof head),maxflow+=dfs(S,2147483647);
    return maxflow;
}
int main(void)
{
    memset(head,-1,sizeof head);
    int n=gi;
    for(int i=1;i<=N;++i)sqr[i]=i*i;
    int num=1,sum=0;
    while(1)
    {
        int maxsqr=lower_bound(sqr+1,sqr+N+1,2*num)-sqr-1;
        int minsqr=upper_bound(sqr+1,sqr+N+1,num)-sqr;
        link(S,num,1),link(num+N,T,1);  
        for(int i=maxsqr;i>=minsqr;--i)link(sqr[i]-num,num+N,1);
        sum+=dinic();
        if(num-sum>n)break;
        ++num;
    }
    --num;
    pi(num,'\n');
    static int to[50007];
    for(int k=1;k<=num;++k)
        for(int i=head[k];~i;i=e[i].nxt)
            if(!e[i].flow){if(e[i].v>N)to[k]=e[i].v-N;break;}
    static int vis[50007];
    for(int i=1;i<=num;i++)
        if(!vis[i])
        {
            for(int k=i;k;k=to[k])vis[k]=1,pi(k,' ');
            putchar('\n');
        }
    return 0;
}

Posted by allaboutthekick on Sat, 19 Oct 2019 14:59:20 -0700