【codevs1234】魔术球问题
来源:互联网 发布:前锦网络南京地址 编辑:程序博客网 时间:2024/05/19 13:20
好题!一开始没想到,看了题解之后发现其实这样的增广方法以前是见过的,每次增加一个结点,然后跑最大流看是否能继续增广,直到不能增广为止,我记得POJ2391也是这样的增广方法,不过那个是二分答案每次重新建图求最大流.
#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<algorithm>#include<queue>using namespace std;const int N=10010,inf=0x3f3f3f3f;int m,n,te,sz,s,t;int vis[N],matching[N],p[N],can[N],cur[N],head[N],d[N],num[N];struct edge{ int u,v,cap,flow,next;}e[100010];queue<int>q;void add(int u,int v,int cap){ e[++te].u=u; e[te].v=v; e[te].flow=0; e[te].cap=cap; e[te].next=head[u]; head[u]=te;}void insert(int u,int v,int cap){add(u,v,cap),add(v,u,0);}int augment(){ int a=inf,x=t; while(x!=s) { a=min(a,e[p[x]].cap-e[p[x]].flow); x=e[p[x]].u; } x=t; while(x!=s) { e[p[x]].flow+=a; e[p[x]^1].flow-=a; x=e[p[x]].u; } return a;}void bfs(){ while(!q.empty())q.pop(); memset(d,0,sizeof(d)); q.push(t); while(!q.empty()) { int u=q.front(); for (int i=head[u];i;i=e[i].next) { int v=e[i].v; if (e[i].cap==0&&!d[v]) d[v]=d[u]+1,q.push(v); } q.pop(); }}int isap(){ int flow=0,x=s; memset(num,0,sizeof(num)); copy(head,head+n+1,cur); bfs(); for (int i=1;i<=n;i++) ++num[d[i]]; while(d[s]<n) { if (x==t) { flow+=augment(); x=s; } int ok=0; for (int i=cur[x];i;i=e[i].next) { int v=e[i].v; if (e[i].cap>e[i].flow&&d[v]+1==d[x]) { p[v]=i; ok=1; cur[x]=i; x=v; break; } } if (!ok) { if (--num[d[x]]==0)break; int mx=n-1; for (int i=head[x];i;i=e[i].next) if (e[i].cap>e[i].flow)mx=min(mx,d[e[i].v]); num[d[x]=mx+1]++; cur[x]=head[x]; if (x!=s)x=e[p[x]].u; } } return flow;}int main(){ memset(vis,0,sizeof(vis)); memset(matching,-1,sizeof(matching)); int k=1;te=1; memset(can,0,sizeof(can)); for (int i=1;i*i<=4000;++i) can[i*i]=1; s=1,t=2;n=2; cin>>m; for (int i=0;i<=m;k++) { insert(s,n+1,1); insert(n+2,t,1); n+=2; for (int j=1;j<k;j++) if (can[k+j])insert((j<<1)+1,n,1);// for (int p=2;p<=te;p+=2)// cout<<e[p].u<<' '<<e[p].v<<' '<<e[p].cap<<endl;// getchar();// cout<<isap()<<endl; if (!isap())i++; } n-=2;k-=2; for (int i=3;i<=n;i+=2) { for (int j=head[i];j;j=e[j].next) { int v=e[j].v-1>>1; if (e[j].flow==1) matching[i>>1]=v; } } cout<<k<<endl; for (int i=1;i<=k;i++) { int x=i; if (!vis[i]) { while(1) { vis[x]=1; printf("%d ",x); if (matching[x]==-1)break; else x=matching[x]; } cout<<endl; } }}
0 0
- 【codevs1234】魔术球问题
- swust1739: 魔术球问题
- 魔术球问题
- P2765 魔术球问题
- luogu2765 魔术球问题
- 魔术球问题
- 魔术球问题 网络流
- Power OJ 魔术球问题
- 魔术球问题(网络24题,三)
- 【网络流24题】魔术球问题
- 【网络流24题】魔术球问题
- 【网络流24题】魔术球问题
- 2017.3.25 魔术球问题 思考记录
- cogs 魔术球问题(简化版)
- [网络流24题]魔术球问题
- 魔术索引问题
- 线性规划与网络流24题 04魔术球问题
- nefu486魔术球问题(增加节点最大流模板)
- pycharm Cannot find declaration to go to
- Surprise ! I'm back!
- js装饰者模式
- display的属性及属性值意义
- 2017.2.27PAT level B 1003
- 【codevs1234】魔术球问题
- 插入排序算法
- java__给定由大写,小写字母和空格组成的字符串,返回 最后 一个单词的长度。 如果输入中不存在单词,返回 0。
- textView.setCompoundDrawablesWithIntrinsicBounds(item.mDrawable, item.mDrawable , null, null);
- leetcode-110-Balanced Binary Tree
- List<object[]>遍历出错
- 较简单的修改和添加功能(链接数据库)
- IO流_PrintWriter实现自动刷新和换行
- 《Netty in Action》中文版—第五章 ByteBuf