拆点+最大流,对与拆开的点建立容量为最多跳几次的边,在建立源点到每个点的边,容量为那有多少只企鹅,最后让互相能到的点建立边。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N=800,M=100000; 6 const int inff=1<<29; 7 const double eps=1e-8; 8 int head[N],nc; 9 struct edge 10 { 11 int x,y,next; 12 int cap; 13 } edge[M*3]; 14 void add(int x,int y,int cap) 15 { 16 edge[nc].x=x; 17 edge[nc].y=y; 18 edge[nc].cap=cap; 19 edge[nc].next=head[x]; 20 head[x]=nc++; 21 edge[nc].x=y; 22 edge[nc].y=x; 23 edge[nc].cap=0; 24 edge[nc].next=head[y]; 25 head[y]=nc++; 26 } 27 int num[N],h[N],S,T,n; 28 int findpath(int x,int flow) 29 { 30 if(x==T) 31 return flow; 32 int res=flow,pos=n-1; 33 for(int i=head[x]; i!=-1; i=edge[i].next) 34 { 35 int y=edge[i].y; 36 if(h[x]==h[y]+1&&edge[i].cap>0) 37 { 38 int tp=findpath(y,min(edge[i].cap,res)); 39 res-=tp; 40 edge[i].cap-=tp; 41 edge[i^1].cap+=tp; 42 if(!res||h[S]==n) 43 return flow-res; 44 } 45 if(edge[i].cap>0&&h[y]<pos) 46 pos=h[y]; 47 } 48 if(res==flow) 49 { 50 num[h[x]]--; 51 if(num[h[x]]==0) 52 { 53 h[S]=n; 54 return flow-res; 55 } 56 h[x]=pos+1; 57 num[h[x]]++; 58 } 59 return flow-res; 60 } 61 int Sap() 62 { 63 memset(h,0,sizeof(h)); 64 memset(num,0,sizeof(num)); 65 int ans=0; 66 num[0]=n; 67 while(h[S]!=n) 68 ans+=findpath(S,inff); 69 return ans; 70 } 71 bool g[105][105]; 72 struct data 73 { 74 double x,y; 75 int have,cap; 76 }po[105]; 77 inline double getdis2(data a,data b) 78 { 79 return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y); 80 } 81 int main() 82 { 83 int TT; 84 for(scanf("%d",&TT);TT;TT--) 85 { 86 double len; 87 int m; 88 scanf("%d%lf",&m,&len); 89 memset(g,false,sizeof(g)); 90 len=len*len;n=m*2+1; 91 for(int i=0;i<m;i++) 92 { 93 scanf("%lf%lf%d%d",&po[i].x,&po[i].y,&po[i].have,&po[i].cap); 94 for(int j=0;j<i;j++) 95 if(getdis2(po[i],po[j])<len+eps) 96 g[j][i]=g[i][j]=true; 97 } 98 int ans[105],top=0,have; 99 S=n-1; 100 for(int i=0;i<m;i++) 101 { 102 T=i; 103 memset(head,-1,sizeof(head)); 104 have=nc=0; 105 for(int j=0;j<m;j++) 106 { 107 add(j,j+m,po[j].cap); 108 add(S,j,po[j].have); 109 have+=po[j].have; 110 for(int k=0;k<m;k++) 111 { 112 if(g[j][k]) 113 add(j+m,k,10000); 114 } 115 } 116 if(Sap()==have) 117 ans[top++]=i; 118 } 119 if(top==0) 120 printf("-1\n"); 121 else 122 { 123 for(int i=0;i<top-1;i++) 124 { 125 printf("%d ",ans[i]); 126 } 127 printf("%d\n",ans[top-1]); 128 } 129 } 130 return 0; 131 }