POJ 3498

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

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 }

你可能感兴趣的:(poj)