好贷网好贷款

poj 3498 网络流 拆点

发布时间:2016-12-3 12:47:03 编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"poj 3498 网络流 拆点",主要涉及到poj 3498 网络流 拆点方面的内容,对于poj 3498 网络流 拆点感兴趣的同学可以参考一下。

题意:某个冰块上有a只企鹅,总共可以跳出去b只,问是否可能所有的企鹅都跳到某一块冰块上,输出所有的可能的冰块的编号。 由于每个点只能跳出去m只企鹅,所以要拆点 假如不拆点,一个点到另一个点可能会跳多于m只企鹅  通过拆点后u->u'间的容量来完成题目的要求(对点的一些限制) 建图:i->i+n 容量为m    i+n->j容量为INF 新建源点s,s->i的容量为i点企鹅的个数 然后枚举汇点求最大流就可以判断某个点是否符合条件 View Code #include<stdio.h>#include<cmath>#include<string.h>#include<algorithm>using namespace std;const double eps = 1e-8;const int MAX=10000;const int INF=1000000000;struct point { int a,b; double x,y;}p[200];double D;double Dis(point a,point b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}struct{ int v,c,next;}edge[1000000];int E,head[MAX];int gap[MAX],cur[MAX];int pre[MAX],dis[MAX];void add_edge(int s,int t,int c,int cc){ edge[E].v=t; edge[E].c=c; edge[E].next=head[s]; head[s]=E++; edge[E].v=s; edge[E].c=cc; edge[E].next=head[t]; head[t]=E++;}int min(int a,int b){return (a==-1||b<a)?b:a;}int SAP(int s,int t,int n){ memset(gap,0,sizeof(gap)); memset(dis,0,sizeof(dis)); int i; for(i=0;i<n;i++)cur[i]=head[i]; int u=pre[s]=s,maxflow=0,aug=-1,v; gap[0]=n; while(dis[s]<n) {loop: for(i=cur[u];i!=-1;i=edge[i].next) { v=edge[i].v; if(edge[i].c>0&&dis[u]==dis[v]+1) { aug=min(aug,edge[i].c); pre[v]=u; cur[u]=i; u=v; if(u==t) { for(u=pre[u];v!=s;v=u,u=pre[u]) { edge[cur[u]].c-=aug; edge[cur[u]^1].c+=aug; } maxflow+=aug; aug=-1; } goto loop; } } int mindis=n; for(i=head[u];i!=-1;i=edge[i].next) { v=edge[i].v; if(edge[i].c>0&&dis[v]<mindis) { cur[u]=i; mindis=dis[v]; } } if((--gap[dis[u]])==0)break; gap[dis[u]=mindis+1]++; u=pre[u]; } return maxflow;}int main(){ int n,i,a,b,j,t; scanf("%d",&t); while(t--) { int sum=0; memset(head,-1,sizeof(head)); E=0; int s=0,t=n+1; scanf("%d%lf",&n,&D); for(i=1;i<=n;i++) { scanf("%lf%lf%d%d",&p[i].x,&p[i].y,&p[i].a,&p[i].b); sum+=p[i].a; add_edge(s,i,p[i].a,0); add_edge(i,i+n,p[i].b,0); } for(i=1;i<=n;i++) { for(j=i+1;j<=n;j++) { if(Dis(p[i],p[j])<D) { add_edge(n+i,j,INF,0); add_edge(n+j,i,INF,0); } } } int flag=0; for(i=1;i<=n;i++) { if(SAP(s,i,2*n+1)==sum) { printf("%d ",i-1); flag=1; } for(j=0;j<E;j+=2) edge[j].c+=edge[j^1].c,edge[j^1].c=0; //每次流完之后恢复原图 } if(!flag) printf("-1\n"); else printf("\n"); }}

上一篇:字典树 + DP
下一篇:[置顶] 在IntelliJ下如何做parameterize method的重构

相关文章

相关评论