HLG 1512 March of the Penguins
题意 : 已知有n 个浮冰 ,和每个企鹅可以跳跃的最大距离,知道了每个浮冰的坐标,和该浮冰上一开始有的企鹅数量,和 该浮冰最多能承受的跳跃次数,跳跃次数是指从该浮冰跳出的最大次数,浮冰的编号从 0 开始, 里面哪些浮冰满足 最后所有的企鹅都能够到达。
分析: 建立一个超级 源点 s=0 ,将每个浮冰分成两个点,左边的点记为 1..n ,右面的点依次为 n+1..n+n,在浮冰 i 和 i+n 之间连一条从i 到 i+n 的边,容量设为 浮冰 i 上的
最大跳跃次数,在源点 s 和 每块冰 i(1..n)之间连一条从 s 到 i 的边,容量设为冰 i 上初始的企鹅数量,即为该点的初始流量,如果 冰 i 和 冰 j 的距离小于等于企鹅可以跳跃的最大距离,即可以从 i 跳到 j,也可以从j 跳到 i ,在 冰 i+n 和冰 j 之间连一条容量为 INF 的边,因为冰 j 的跳入次数没有限制,所以容量为无穷大,在 j+n和i 之间也连一条同样的边, 最后分别以 冰(1..n)为汇点求最大流,如果最大流为 企鹅数量 M ,则该浮冰就可以作为最终的落脚点。
邻接矩阵:
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<math.h> #define INF 0x1f1f1f1f #define min(a,b)(a)<(b)?(a):(b) #define clr(x)memset(x,0,sizeof(x)) int c[202][202]; int gap[202]; int dis[202]; void init(int s,int u,int n) { int v,x,front=0,rear=0; int q[203]; clr(gap); memset(dis,0xff,sizeof(dis)); q[rear++]=u; dis[u]=0; while(front<rear) { x=q[front++]; gap[dis[x]]++; for(v=0;v<=n;v++) if(dis[v]==-1&&c[v][x]>0) { dis[v]=dis[x]+1; q[rear++]=v; } } } int sap(int s,int u,int n) { init(s,u,n); int flag,flow=0,top=s,i,j,k; int pre[203],low[203]; clr(low); while(dis[s]<=n) { flag=0; low[s]=INF; for(i=0;i<=n;i++) if(c[top][i]>0&&dis[top]==dis[i]+1&&dis[i]>=0) { flag=1; break; } if(flag) { low[i]=c[top][i]; low[i]=min(low[i],low[top]); pre[i]=top; top=i; if(top==u) { flow+=low[u]; j=top; while(j!=s) { k=pre[j]; c[k][j]-=low[u]; c[j][k]+=low[u]; j=k; } top=s; clr(low); } } else { int dmin=n; for(j=0;j<=n;j++) if(c[top][j]>0&&dis[j]+1<dmin&&dis[j]>=0) dmin=dis[j]+1; gap[dis[top]]--; if(gap[dis[top]]==0) break; gap[dmin]++; dis[top]=dmin; if(top!=s) top=pre[top]; } } return flow; } struct node { double x,y; int num,ti; }pe[102]; double dist(node a,node b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } struct edge { int from,to,flow; }e[1000000]; int tot; void add(int s,int u,int f) { e[tot].from=s; e[tot].to=u; e[tot++].flow=f; } int res[102]; int main() { // freopen("D:ce.txt","r",stdin); int t,n,i,j,top,max_flow,pe_num; double d; scanf("%d",&t); while(t--) { scanf("%d%lf",&n,&d); clr(c); tot=0; pe_num=0; for(i=1;i<=n;i++) scanf("%lf%lf%d%d",&pe[i].x,&pe[i].y,&pe[i].num,&pe[i].ti); for(i=1;i<=n;i++) if(pe[i].num) { pe_num+=pe[i].num; c[0][i]=pe[i].num; add(0,i,pe[i].num); } for(i=1;i<=n;i++) if(pe[i].ti) { c[i][i+n]=pe[i].ti; add(i,i+n,pe[i].ti); } for(i=1;i<n;i++) for(j=i+1;j<=n;j++) if(dist(pe[i],pe[j])<=d) { c[i+n][j]=INF; c[j+n][i]=INF; add(i+n,j,INF); add(j+n,i,INF); } top=0; for(i=1;i<=n;i++) { max_flow=sap(0,i,2*n); if(max_flow==pe_num) res[top++]=i-1; for(j=0;j<tot;j++) { c[e[j].from][e[j].to]=e[j].flow; c[e[j].to][e[j].from]=0; } } if(top) { for(i=0;i<top;i++) printf("%d%c",res[i],i==top-1?'\n':' '); } else printf("-1\n"); } return 0; }
前向星:
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<math.h> #define min(a,b)(a)<(b)?(a):(b) const int INF=0x1f1f1f1f; const double eps=1e-8; const int maxn=222; const int maxm=1000003; struct node { int c,next,to; }e[maxm]; int tot; int head[maxn]; void add(int s,int u,int flow) { e[tot].to=u; e[tot].c=flow; e[tot].next=head[s]; head[s]=tot++; } int max_flow(int st,int end,int n) { int numh[maxn],h[maxn],curedge[maxn],pre[maxn]; int cur_flow,maxflow=0,u,tmp,neck,i; memset(h,0,sizeof(h)); memset(numh,0,sizeof(numh)); memset(pre,0xff,sizeof(pre)); for(i=0;i<=n;i++) curedge[i]=head[i]; numh[0]=n+1; u=st; while(h[st]<n+1) { if(u==end) { cur_flow=INF; for(i=st;i!=end;i=e[curedge[i]].to) if(cur_flow>e[curedge[i]].c) { neck=i; cur_flow=e[curedge[i]].c; } for(i=st;i!=end;i=e[curedge[i]].to) { tmp=curedge[i]; e[tmp].c-=cur_flow; e[tmp^1].c+=cur_flow; } maxflow+=cur_flow; u=neck; } for(i=curedge[u];i!=-1;i=e[i].next) if(e[i].c&&h[u]==h[e[i].to]+1) break; if(i!=-1) { curedge[u]=i; pre[e[i].to]=u; u=e[i].to; } else { if(--numh[h[u]]==0) break; curedge[u]=head[u]; for(tmp=n,i=head[u];i!=-1;i=e[i].next) if(e[i].c) tmp=min(tmp,h[e[i].to]); h[u]=tmp+1; ++numh[h[u]]; if(u!=st) u=pre[u]; } } return maxflow; } struct point { double x,y; int in,ti; }p[103]; double di(point a,point b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } int res[103]; struct tm { int ii,fo; }tp[1000000]; int main() { int n,a,b,w,i,s,j,t,ff,tt,sum,tr; double dd; scanf("%d",&t); while(t--) { scanf("%d%lf",&n,&dd); tot=0; memset(head,-1,sizeof(head)); tr=0; tt=0; sum=0; for(i=1;i<=n;i++) { scanf("%lf%lf%d%d",&p[i].x,&p[i].y,&p[i].in,&p[i].ti); sum+=p[i].in; } s=0; for(i=1;i<=n;i++) { add(s,i,p[i].in); tp[tr].ii=tot-1; tp[tr++].fo=p[i].in; add(i,s,0); tp[tr].ii=tot-1; tp[tr++].fo=0; } for(i=1;i<=n;i++) { add(i,i+n,p[i].ti); tp[tr].ii=tot-1; tp[tr++].fo=p[i].ti; add(i+n,i,0); tp[tr].ii=tot-1; tp[tr++].fo=0; } for(i=1;i<=n;i++) for(j=i+1;j<=n;j++) if(di(p[i],p[j])<=dd+eps) { add(i+n,j,INF); tp[tr].ii=tot-1; tp[tr++].fo=INF; add(j,i+n,0); tp[tr].ii=tot-1; tp[tr++].fo=0; add(j+n,i,INF); tp[tr].ii=tot-1; tp[tr++].fo=INF; add(i,j+n,0); tp[tr].ii=tot-1; tp[tr++].fo=0; } for(i=1;i<=n;i++) { ff=max_flow(0,i,2*n); if(ff==sum) res[tt++]=i-1; for(j=0;j<tr;j++) // 恢复原本的容量 e[tp[j].ii].c=tp[j].fo; } if(tt) { for(i=0;i<tt;i++) printf("%d%c",res[i],i==tt-1?'\n':' '); } else printf("-1\n"); } return 0; }