其实每个柱子就相当于最小路径覆盖中的一根柱子。
我们要在有n条路径的最小覆盖中加尽量多的点。
所以我们枚举答案加边即可。
By:大奕哥
1 #include<iostream> 2 #include<cstdlib> 3 #include<cstdio> 4 #include<algorithm> 5 #include<cstring> 6 #include<queue> 7 #include<vector> 8 #include<cmath> 9 using namespace std; 10 const int N=100005; 11 int n,m,s=0,t=100000,head[N],d[N],vis[N],w[N],cnt=-1; 12 inline int read(){ 13 int x=0,f=1;char ch=getchar(); 14 while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} 15 while(ch>=‘0‘&&ch<=‘9‘)x=(x<<1)+(x<<3)+ch-‘0‘,ch=getchar(); 16 return x*f; 17 } 18 struct node{ 19 int to,nex,w; 20 }e[N<<1]; 21 void add(int x,int y,int w) 22 { 23 e[++cnt].to=y;e[cnt].w=w;e[cnt].nex=head[x];head[x]=cnt; 24 e[++cnt].to=x;e[cnt].w=0;e[cnt].nex=head[y];head[y]=cnt; 25 } 26 queue<int>q; 27 bool bfs(int x,int y) 28 { 29 memset(d,-1,sizeof(d)); 30 d[x]=0;q.push(x); 31 while(!q.empty()) 32 { 33 int x=q.front();q.pop(); 34 for(int i=head[x];i!=-1;i=e[i].nex) 35 { 36 int y=e[i].to; 37 if(!e[i].w||d[y]!=-1)continue; 38 d[y]=d[x]+1; 39 q.push(y); 40 } 41 } 42 return d[y]!=-1; 43 } 44 int dfs(int x,int w,int yy) 45 { 46 if(!w||x==yy)return w; 47 int s=0; 48 for(int i=head[x];i!=-1;i=e[i].nex) 49 { 50 int y=e[i].to; 51 if(!e[i].w||d[y]!=d[x]+1)continue; 52 int flow=dfs(y,min(w-s,e[i].w),yy); 53 if(!flow){ 54 d[y]=-1;continue; 55 } 56 e[i].w-=flow;e[i^1].w+=flow; 57 vis[x]=y;s+=flow; 58 if(s==w)return s; 59 } 60 return s; 61 } 62 int dinic() 63 { 64 int ans=0; 65 while(bfs(s,t)){ 66 ans+=dfs(s,1e9,t); 67 } 68 return ans; 69 } 70 int main() 71 { 72 n=read(); 73 memset(head,-1,sizeof(head)); 74 int ans=0,num=0,x,y; 75 while(ans<=n) 76 { 77 num++; 78 add(s,num<<1,1);add(num<<1|1,t,1); 79 for(int i=sqrt(num)+1;i*i<(num<<1);++i) 80 add((i*i-num)<<1,num<<1|1,1); 81 if(!dinic())w[++ans]=num; 82 } 83 printf("%d\n",num-1); 84 for(int i=1;i<=n;++i) 85 { 86 x=w[i];x<<=1; 87 while(x) 88 { 89 if((x&1))x^=1; 90 printf("%d ",x>>1); 91 y=vis[x]; 92 vis[x]=0; 93 x=y; 94 } 95 printf("\n"); 96 } 97 return 0; 98 }