拆点+最大流,对与拆开的点建立容量为最多跳几次的边,在建立源点到每个点的边,容量为那有多少只企鹅,最后让互相能到的点建立边。

View Code
  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 }