loj 1154(最大流+枚举汇点)

来源:互联网 发布:兔子白网络 编辑:程序博客网 时间:2024/05/22 06:53

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=26868

思路:拆点,容量为最多能跳的步数,然后设立一个超级源点,源点与各点两连边,容量为一开始的企鹅数,最后就是枚举汇点了,跑最大流验证即可。

  1 #include<iostream>  2 #include<cstdio>  3 #include<cstring>  4 #include<algorithm>  5 #include<queue>  6 #include<cmath>  7 using namespace std;  8 #define MAXN 222  9 #define MAXM 222222 10 #define inf 1<<30 11 #define FILL(a,b) memset(a,b,sizeof(a)) 12  13 struct Edge{ 14     int v,cap,next; 15 }edge[MAXM]; 16  17 int n,vs,vt,NV,NE,head[MAXN]; 18 double d; 19  20  21 void Insert(int u,int v,int cap) 22 { 23     edge[NE].v=v; 24     edge[NE].cap=cap; 25     edge[NE].next=head[u]; 26     head[u]=NE++; 27  28     edge[NE].v=u; 29     edge[NE].cap=0; 30     edge[NE].next=head[v]; 31     head[v]=NE++; 32 } 33  34 int level[MAXN],gap[MAXN]; 35 void bfs(int vt) 36 { 37     FILL(level,-1); 38     FILL(gap,0); 39     queue<int>que; 40     que.push(vt); 41     level[vt]=0; 42     gap[0]++; 43     while(!que.empty()){ 44         int u=que.front(); 45         que.pop(); 46         for(int i=head[u];i!=-1;i=edge[i].next){ 47             int v=edge[i].v; 48             if(level[v]!=-1)continue; 49             level[v]=level[u]+1; 50             gap[level[v]]++; 51             que.push(v); 52         } 53     } 54 } 55  56 int pre[MAXN],cur[MAXN]; 57 int SAP(int vs,int vt) 58 { 59     bfs(vt); 60     memcpy(cur,head,sizeof(head)); 61     int u=pre[vs]=vs,aug=inf,maxflow=0; 62     gap[0]=NV; 63     while(level[vs]<NV){ 64         bool flag=false; 65         for(int &i=cur[u];i!=-1;i=edge[i].next){ 66             int v=edge[i].v; 67             if(edge[i].cap>0&&level[u]==level[v]+1){ 68                 flag=true; 69                 aug=min(aug,edge[i].cap); 70                 pre[v]=u; 71                 u=v; 72                 if(v==vt){ 73                     maxflow+=aug; 74                     for(u=pre[u];v!=vs;v=u,u=pre[u]){ 75                         edge[cur[u]].cap-=aug; 76                         edge[cur[u]^1].cap+=aug; 77                     } 78                     aug=inf; 79                 } 80                 break; 81             } 82         } 83         if(flag)continue; 84         int minlevel=NV; 85         for(int i=head[u];i!=-1;i=edge[i].next){ 86             int v=edge[i].v; 87             if(edge[i].cap>0&&level[v]<minlevel){ 88                 cur[u]=i; 89                 minlevel=level[v]; 90             } 91         } 92         if(--gap[level[u]]==0)break; 93         level[u]=minlevel+1; 94         gap[level[u]]++; 95         u=pre[u]; 96     } 97     return maxflow; 98 } 99 100 struct Node{101     double x,y;102     int num,step;103 }node[MAXN];104 105 double Get_Dist(int i,int j)106 {107     double d1=(node[i].x-node[j].x)*(node[i].x-node[j].x);108     double d2=(node[i].y-node[j].y)*(node[i].y-node[j].y);109     return sqrt(d1+d2);110 }111 112 void Build(int ed)113 {114     NE=0;115     FILL(head,-1);116     vs=0,vt=2*n+1;117     NV=vt+1;118     for(int i=1;i<=n;i++){119         Insert(i,i+n,node[i].step);120         Insert(vs,i,node[i].num);121     }122     for(int i=1;i<=n;i++){123         for(int j=i+1;j<=n;j++){124             if(Get_Dist(i,j)<=d){125                 Insert(i+n,j,inf);126                 Insert(j+n,i,inf);127             }128         }129     }130     Insert(ed,vt,inf);131 }132 133 int main()134 {135     int _case,ans,sum,flag,t=1;136     scanf("%d",&_case);137     while(_case--){138         scanf("%d%lf",&n,&d);139         sum=0;140         for(int i=1;i<=n;i++){141             scanf("%lf%lf%d%d",&node[i].x,&node[i].y,&node[i].num,&node[i].step);142             sum+=node[i].num;143         }144         flag=0;145         printf("Case %d:",t++);146         //枚举集中点147         for(int i=1;i<=n;i++){148             Build(i);149             if(SAP(vs,vt)==sum)flag=1,printf(" %d",i-1);150         }151         if(!flag)printf(" -1");152         puts("");153     }154     return 0;155 }
View Code

 

0 0