HNU Suiting Weavers 【最大流】
题意:有 n 个鸟,知道了每只鸟的活动半径和每个鸟窝在一开的时候有的草的数量,有m 个草堆,每个草堆有一定数量的草,知道了每个草堆的位置,
所有能被鸟捡到即被鸟覆盖到地方的草到最后都会被捡完,问是否存在一种情况使得所有鸟最后拥有的草的数量不超过第一只鸟用有的草的数量。
分析: 首先让第一只鸟将可以捡到的草全部捡完,这时候拥有的草的数量为第一只鸟最后所能拥有的最多的草的数量记为k,限制其他鸟可以拥有的
草的数量不超过 k,看最后这些鸟能否将能捡的草捡完。
建图:
源点 s=0,汇点 t=(n-1)+m+1
鸟的编号1..n-1,草堆编号n..n+m-1
在源点和每只鸟之间连一条边容量设为 k,
如果某只鸟能够到某个草堆就在其间建一条容量为 草堆草数量的边
在每个草堆和汇点之间连一条容量为草堆草数量的边。
求最大流,判断是否等于能捡到草的总数。
#include<stdio.h> #include<string.h> #include<math.h> #define clr(x)memset(x,0,sizeof(x)) #define maxn 600 #define INF 0x1f1f1f1f int c[maxn][maxn]; int gap[maxn]; int dis[maxn]; void init(int s,int t,int n) { int v,x,q[maxn],front=0,rear=0; memset(gap,0,sizeof(gap)); memset(dis,0xff,sizeof(dis)); q[rear++]=t; dis[t]=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_flow(int s,int t,int n) { init(s,t,n); int top=s,i,j,k; int pre[maxn]; int low[maxn]; int flow=0; memset(low,0,sizeof(low)); while(dis[s]<n) { int 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]; if(low[i]>low[top]) low[i]=low[top]; pre[i]=top; top=i; if(top==t) { flow+=low[t]; j=top; while(j!=s) { k=pre[j]; c[k][j]-=low[t]; c[j][k]+=low[t]; j=k; } top=s; memset(low,0,sizeof(low)); } } else { int min=n-1; for(j=0;j<n;j++) // 从下标的最小值最大值,有时候最后一个可能是n-1 !! { // 昭和 top 相邻 dis 最小的点 if(c[top][j]>0&&dis[j]+1<min&&dis[j]>=0) min=dis[j]+1; } gap[dis[top]]--; if(gap[dis[top]]==0) break; gap[min]++; dis[top]=min; // 更新 top 距离值 if(top!=s) // 回溯找其他的路径 top=pre[top]; } } return flow; } struct node { double x,y,r; int init; }b[maxn],s[maxn],w; double d(node a,node b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } int vis[maxn]; int vv[maxn]; int main() { int st,en,T,i,j,n,m,tot; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); n--; tot=0; clr(vis); clr(c); clr(vv); scanf("%lf%lf%d%lf",&w.x,&w.y,&w.init,&w.r); for(i=1;i<=n;i++) scanf("%lf%lf%d%lf",&b[i].x,&b[i].y,&b[i].init,&b[i].r); for(i=1;i<=m;i++) scanf("%lf%lf%d",&s[i].x,&s[i].y,&s[i].init); for(i=1;i<=m;i++) if(d(w,s[i])<=w.r) { vis[i]=1; w.init+=s[i].init; } int flag=0; st=0; en=n+m+1; for(i=1;i<=n;i++) { if(b[i].init>w.init) { flag=1; break; } else c[st][i]=w.init-b[i].init; } if(flag) { printf("Lonesome Willy\n"); continue; } for(i=1;i<=n;i++) for(j=1;j<=m;j++) if(!vis[j]&&d(b[i],s[j])<=b[i].r) { vv[j]=1; c[i][n+j]=s[j].init; } for(i=1;i<=m;i++) if(vv[i]) tot+=s[i].init; for(i=1;i<=m;i++) c[i+n][en]=s[i].init; int res=sap_flow(st,en,n+m+2); if(res==tot) printf("Suiting Success\n"); else printf("Lonesome Willy\n"); } return 0; }