「luogu2765」魔术球问题

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=60,M=4010,oo=2e9;
 4 int n,ss=4000,tt=4001,f[M];
 5 bool vis[M];
 6 struct Edge{
 7     int from,to,flow,cap;
 8     Edge(int _from=0,int _to=0,int _flow=0,int _cap=0):from(_from),to(_to),flow(_flow),cap(_cap){}
 9 };
10 int edge_tot;
11 Edge edge[100500];
12 vector<int>point[M];
13 void add_edge(int f,int t,int c){
14     edge[edge_tot]=Edge(f,t,0,c);
15     point[f].push_back(edge_tot++);
16     edge[edge_tot]=Edge(t,f,0,0);
17     point[t].push_back(edge_tot++);
18     return;
19 }
20 int level[M];
21 bool bfs(){
22     memset(level,0,sizeof(level));
23     queue<int>q;
24     q.push(ss);
25     level[ss]=1;
26     int x;
27     while(!q.empty()){
28         x=q.front();q.pop();
29         for(int i=0;i<point[x].size();i++){
30             Edge e=edge[point[x][i]];
31             if(e.cap>e.flow&&!level[e.to]){
32                 int nxt=edge[point[x][i]].to;
33                 level[nxt]=level[x]+1;
34                 q.push(nxt);
35             }
36         }
37     }
38     return level[tt];
39 }
40 int dfs(int k,int a){
41     if(k==tt||!a) return a;
42     int temp,ans=0;
43     for(int i=0;i<point[k].size();i++){
44         Edge& e=edge[point[k][i]];
45         if(e.cap>e.flow&&level[e.to]==level[k]+1&&(temp=dfs(e.to,min(a,e.cap-e.flow)))){
46             ans+=temp,a-=temp;
47             e.flow+=temp,edge[point[k][i]^1].flow-=temp;
48         }
49         if(!a) return ans;
50     }
51     return ans;
52 }
53 int dinic(){
54     int ans=0;
55     while(bfs())
56         ans+=dfs(ss,oo);
57     return ans;
58 }
59 int main(){
60     scanf("%d",&n);
61     int ans,t1,t2;
62     for(ans=1;1;ans++){
63         add_edge(ss,(ans<<1)-1,1);add_edge((ans<<1),tt,1);
64         for(int i=1;i<ans;i++){
65             t1=i+ans,t2=sqrt(t1);
66             if(t2*t2==t1) add_edge((ans<<1)-1,(i<<1),1);
67         }
68         t1=dinic();
69         if(ans-t1>n) break;
70         for(int i=0;i<edge_tot;i++) edge[i].flow=0;
71     }
72     ans--;
73     printf("%d\n",ans);
74     for(int i=1;i<=ans;i++)
75         for(int j=0;j<point[(i<<1)-1].size();j++)
76             if(edge[point[(i<<1)-1][j]].flow>0){f[(edge[point[(i<<1)-1][j]].to)>>1]=i;break;}
77     for(int i=1;i<=ans;i++){
78         if(vis[i]) continue;
79         printf("%d ",i);
80         vis[i]=1,t1=f[i];
81         while(t1){
82             printf("%d ",t1);
83             vis[t1]=1,t1=f[t1];
84         }
85         printf("\n");
86     }
87     return 0;
88 }

 

posted @ 2018-03-08 13:12  Cupcake  阅读(122)  评论(0编辑  收藏  举报