魔术球问题
这一题也不难,就每次增加一个就暴力连边就行了,然后每次都跑一遍dinic就可以了
#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int MAXN=170005;
const int MAXM=170005;
const int py = 2000;
int d[MAXN],n,m,p[MAXN],eid,S,T,x,y,vis[MAXN],now,qwq,ans[MAXN];
struct A{
int v,c,next;
}e[MAXM];
void init(){
memset(p,-1,sizeof(p));
eid=0;
}
void add(int u,int v,int c){
e[eid].v=v;
e[eid].c=c;
e[eid].next=p[u];
p[u]=eid++;
}
void insert(int u,int v,int c){
add(u,v,c);
add(v,u,0);
}
int bfs(){
memset(d,-1,sizeof(d));
queue<int>q;
d[S]=0;
q.push(S);
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=p[u];i!=-1;i=e[i].next){
int v=e[i].v;
if(e[i].c>0&&d[v]==-1){
d[v]=d[u]+1;
q.push(v);
}
}
}
return (d[T]!=-1);
}
int dfs(int u,int flow){
if(u==T) return flow;
int ret=0;
for(int i=p[u];i!=-1;i=e[i].next){
int v=e[i].v;
if(e[i].c>0&&d[v]==d[u]+1){
int tmp=dfs(v,min(flow,e[i].c));
e[i].c-=tmp;
e[i^1].c+=tmp;
flow-=tmp;
ret+=tmp;
if(!flow) break;
}
}
if(!ret) d[u]=-1;
return ret;
}
int Dinic(){
int ret=0;
while(bfs()){
ret+=dfs(S,INF);
}
return ret;
}
void dfss(int x){
if(vis[x]) return;
vis[x]=1;printf("%d ",x);
for(int i = p[x]; i + 1; i = e[i].next){
int v = e[i].v;
if(!e[i].c && v > py)
dfss(v-py);
}
}
void print(){
for(int i = 1; i <= n; i++){
dfss(ans[i]),printf("\n");
}
}
bool check(int x,int y){
int oo=sqrt(x+y);
x=x+y;
oo=oo*oo;
return (x==oo);
}
int main () {
init();
scanf("%d", &n);
S=0;T=py*n;
while(qwq<=n){
now++;
insert(S,now,1);
insert(now+py,T,1);
for(int i=1;i<now;i++){
if(check(now,i)) insert(i,now+py,1);
}
if(!Dinic()) ans[++qwq]=now;
}
printf("%d\n",now-1);
print();
return 0;
}