zoukankan      html  css  js  c++  java
  • poj 3498(最大流+拆点)

    题目链接:http://poj.org/problem?id=3498

    思路:首先设一个超级源点,将源点与各地相连,边容量为各点目前的企鹅数量,然后就是对每个冰块i进行拆点了(i,i+n),边容量为能够接受的受损程度,这样就把点权问题转化为边权问题了,然后就是对于那些能够相互跳跃的冰块之间连边(i+n,j),(j+n,i),边容量为inf。最后就是枚举汇点看是否等于总数。

      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 2222222
     10 #define inf 1<<30
     11 
     12 struct Edge{
     13     int v,cap,next;
     14 }edge[MAXM];
     15 
     16 int n,NE,vs,vt,NV;
     17 double dist;
     18 int head[MAXN];
     19 
     20 void Insert(int u,int v,int cap)
     21 {
     22     edge[NE].v=v;
     23     edge[NE].cap=cap;
     24     edge[NE].next=head[u];
     25     head[u]=NE++;
     26 
     27     edge[NE].v=u;
     28     edge[NE].cap=0;
     29     edge[NE].next=head[v];
     30     head[v]=NE++;
     31 }
     32 
     33 int level[MAXN],gap[MAXN];
     34 void bfs(int vt)
     35 {
     36     memset(level,-1,sizeof(level));
     37     memset(gap,0,sizeof(gap));
     38     level[vt]=0;
     39     gap[level[vt]]++;
     40     queue<int>que;
     41     que.push(vt);
     42     while(!que.empty()){
     43         int u=que.front();
     44         que.pop();
     45         for(int i=head[u];i!=-1;i=edge[i].next){
     46             int v=edge[i].v;
     47             if(level[v]!=-1)continue;
     48             level[v]=level[u]+1;
     49             gap[level[v]]++;
     50             que.push(v);
     51         }
     52     }
     53 }
     54 
     55 int pre[MAXN],cur[MAXN];
     56 int SAP(int vs,int vt)
     57 {
     58     bfs(vt);
     59     memset(pre,-1,sizeof(pre));
     60     memcpy(cur,head,sizeof(cur));
     61     int maxflow=0,aug=inf;
     62     int u=pre[vs]=vs;
     63     gap[0]=NV;
     64     while(level[vs]<NV){
     65         bool flag=false;
     66         for(int &i=cur[u];i!=-1;i=edge[i].next){
     67             int v=edge[i].v;
     68             if(edge[i].cap>0&&level[u]==level[v]+1){
     69                 flag=true;
     70                 pre[v]=u;
     71                 u=v;
     72                 aug=min(aug,edge[i].cap);
     73                 if(v==vt){
     74                     maxflow+=aug;
     75                     for(u=pre[v];v!=vs;v=u,u=pre[u]){
     76                         edge[cur[u]].cap-=aug;
     77                         edge[cur[u]^1].cap+=aug;
     78                     }
     79                     aug=inf;
     80                 }
     81                 break;
     82             }
     83         }
     84         if(flag)continue;
     85         int minlevel=NV;
     86         for(int i=head[u];i!=-1;i=edge[i].next){
     87             int v=edge[i].v;
     88             if(edge[i].cap>0&&level[v]<minlevel){
     89                 minlevel=level[v];
     90                 cur[u]=i;
     91             }
     92         }
     93         if(--gap[level[u]]==0)break;
     94         level[u]=minlevel+1;
     95         gap[level[u]]++;
     96         u=pre[u];
     97     }
     98     return maxflow;
     99 }
    100 struct Point{
    101     double x,y;
    102     int num1,num2;
    103 }p[MAXN];
    104 
    105 double Get_dist(int i,int j)
    106 {
    107     double d1=(p[i].x-p[j].x)*(p[i].x-p[j].x);
    108     double d2=(p[i].y-p[j].y)*(p[i].y-p[j].y);
    109     return sqrt(d1+d2);
    110 }
    111 void Build()
    112 {
    113     NE=0;
    114     memset(head,-1,sizeof(head));
    115     vs=0,NV=2*n+1;
    116     for(int i=1;i<=n;i++)Insert(vs,i,p[i].num1);
    117     for(int i=1;i<=n;i++)Insert(i,i+n,p[i].num2);
    118     for(int i=1;i<=n;i++){
    119         for(int j=i+1;j<=n;j++){
    120             if(Get_dist(i,j)<=dist){
    121                 Insert(i+n,j,inf);
    122                 Insert(j+n,i,inf);
    123             }
    124         }
    125     }
    126 }
    127 int ans[MAXN],cnt;
    128 int main()
    129 {
    130     int _case,sum;
    131     scanf("%d",&_case);
    132     while(_case--){
    133         scanf("%d%lf",&n,&dist);
    134         sum=0;
    135         for(int i=1;i<=n;i++){
    136             scanf("%lf%lf%d%d",&p[i].x,&p[i].y,&p[i].num1,&p[i].num2);
    137             sum+=p[i].num1;
    138         }
    139         cnt=0;
    140         for(int i=1;i<=n;i++){
    141             Build();
    142             if(SAP(vs,i)==sum)ans[cnt++]=i;
    143         }
    144         if(cnt){
    145             for(int i=0;i<cnt;i++){
    146                 printf(i?" %d":"%d",ans[i]-1);
    147             }
    148             printf("
    ");
    149         }else
    150             puts("-1");
    151     }
    152     return 0;
    153 }
    View Code
  • 相关阅读:
    【2018.05.05 C与C++基础】C++中的自动废料收集:概念与问题引入
    【2018.04.27 C与C++基础】关于switch-case及if-else的效率问题
    【2018.04.19 ROS机器人操作系统】机器人控制:运动规划、路径规划及轨迹规划简介之一
    March 11th, 2018 Week 11th Sunday
    March 10th, 2018 Week 10th Saturday
    March 09th, 2018 Week 10th Friday
    March 08th, 2018 Week 10th Thursday
    March 07th, 2018 Week 10th Wednesday
    ubantu之Git使用
    AMS分析 -- 启动过程
  • 原文地址:https://www.cnblogs.com/wally/p/3283660.html
Copyright © 2011-2022 走看看