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
  • 相关阅读:
    《世界是数字的》
    IT小小鸟读书笔记
    Codeforces Round #665 Div.2 (CF1401)
    Codeforces Round #662 Div.2 (CF1392)
    std::array的效率问题
    CSS布局学习总结
    TCP中三次握手与四次挥手
    初见Vuex
    初见webpack
    CentOS7使用yum简便安装mysql5.7
  • 原文地址:https://www.cnblogs.com/wally/p/3283660.html
Copyright © 2011-2022 走看看