zoukankan      html  css  js  c++  java
  • POJ 2175 费用流(消圈)

    题意:

     一个城市有n座建筑物,每个建筑物里面有一些人,为了在战争爆发时这些人都可以避难,城市里面建了m座避难所。每座避难所只能容纳有限人数。给出每个建筑物和避难所的坐标(题目要求距离为曼哈顿距离+1)。现在给你一种避难方案,问这种方案是否为最优方案,如果不是,请输出一种比当前更优的方案(不一定最优)。

    答案给出的方案不是最优的,当且仅当存在另一种方案的所有人移动的总路程比答案少。。

    题解:

    建图,费用流超时。。

    然后看了下费用流的消圈算法,就是用来验证当前的费用流是否是最小的。

    消圈定理:残留网络里如果存在负费用圈,那么当前流不是最小费用流。

    负圈有必要解释一下:费用总和是负数,且每条边的剩余流量大于0

    网上好像都是简化版的消圈,我写的是完整版的,更好理解一些,就是边多了一些,不过不太影响速度

    网上的题解都说的那么玄妙,其实就是按照题目给图的答案构造残余网络,然后利用spfa找负圈(负环)判断其是否是最小费用流~

    ps:还以为是我spfa写错了呢。。。原来边权打翻了。。。

    View Code
      1 #include <iostream>
      2 #include <cstdlib>
      3 #include <cstring>
      4 #include <cstdio>
      5 #include <algorithm>
      6 #include <cmath>
      7 
      8 #define N 250
      9 #define M 500000
     10 #define INF 1e9
     11 
     12 using namespace std;
     13 
     14 int head[N],next[M],to[M],pr[M],len[M];
     15 int q[N*M],dis[N],pre[N],im[N];
     16 int map[N][N],hx[N],hy[N],hp[N],sx[N],sy[N],sr[N],sum[N];
     17 int rc[N][N];
     18 bool vis[N];
     19 int n,m,cnt,S,T,rt;
     20 
     21 inline void prep()
     22 {
     23     for(int i=1;i<=n;i++)
     24         for(int j=1;j<=m;j++)
     25             map[i][j]=abs(hx[i]-sx[j])+abs(hy[i]-sy[j])+1;
     26 }
     27 
     28 inline void add(int u,int v,int r,int w)
     29 {
     30     to[cnt]=v; len[cnt]=r; pr[cnt]=w; next[cnt]=head[u]; head[u]=cnt++;
     31 }
     32 
     33 inline void read()
     34 {
     35     memset(sum,0,sizeof sum);
     36     memset(head,-1,sizeof head); cnt=0;
     37     for(int i=1;i<=n;i++) scanf("%d%d%d",&hx[i],&hy[i],&hp[i]);
     38     for(int i=1;i<=m;i++) scanf("%d%d%d",&sx[i],&sy[i],&sr[i]);
     39     prep();
     40     for(int i=1,a;i<=n;i++)
     41         for(int j=1;j<=m;j++)
     42         {
     43             scanf("%d",&a); rc[i][j]=a;
     44             add(i,n+j,INF-a,map[i][j]);
     45             add(n+j,i,a,-map[i][j]);
     46             sum[j]+=a;
     47         }
     48     S=0; T=n+m+1;
     49     for(int i=1;i<=n;i++) add(S,i,0,0),add(i,S,hp[i],0);
     50     for(int i=1;i<=m;i++) add(i+n,T,sr[i]-sum[i],0),add(T,i+n,sum[i],0);
     51 }
     52 
     53 inline int spfa()
     54 {
     55     memset(vis,0,sizeof vis);
     56     memset(dis,0x3f,sizeof dis);
     57     memset(im,0,sizeof im);
     58     memset(pre,-1,sizeof pre);
     59     int h=1,t=2,sta;
     60     dis[T]=0; vis[T]=true; q[1]=T; im[T]++;
     61     while(h<t)
     62     {
     63         sta=q[h++]; vis[sta]=false;
     64         for(int i=head[sta];~i;i=next[i])
     65             if(len[i]&&dis[to[i]]>dis[sta]+pr[i])
     66             {
     67                 dis[to[i]]=dis[sta]+pr[i];
     68                 pre[to[i]]=sta;
     69                 if(!vis[to[i]])
     70                 {
     71                     vis[to[i]]=true; q[t++]=to[i]; ++im[to[i]];
     72                     if(im[to[i]]>n+m+2) return to[i];
     73                 }
     74             }
     75     }
     76     return -1;
     77 }
     78 
     79 inline void go()
     80 {
     81     int rt=spfa();
     82     int st;
     83     if(rt==-1) {puts("OPTIMAL");return;}
     84     puts("SUBOPTIMAL"); 
     85     memset(vis,0,sizeof vis);
     86     int sta=rt;
     87     while(true)
     88     {
     89         if(!vis[sta]) vis[sta]=true,sta=pre[sta];
     90         else {rt=sta;break;}
     91     }
     92     do
     93     {
     94         int from=pre[sta],to=sta;
     95         if(from<=n&&to>n) rc[from][to-n]++;
     96         if(to<=n&&from>n) rc[to][from-n]--;
     97         sta=pre[sta];
     98     }while(sta!=rt);
     99     for(int i=1;i<=n;i++)
    100     {
    101         printf("%d",rc[i][1]);
    102         for(int j=2;j<=m;j++)
    103             printf(" %d",rc[i][j]);
    104         puts("");
    105     }
    106 }
    107 
    108 int main()
    109 {
    110     while(scanf("%d%d",&n,&m)!=EOF) read(),go();
    111     return 0;
    112 }
    没有人能阻止我前进的步伐,除了我自己!
  • 相关阅读:
    Tomcat服务器本地的搭建,以及在 IDEA软件下的配置,以及项目的测试运行(基于supermvc框架下的web)
    数据可视化-EChart2.0.0使用中遇到的2个问题
    数据可视化-EChart2.0使用总结2
    数据可视化-EChart2.0使用总结1
    Mac下有道笔记本问题反馈
    修复bootstrap daterangepicker中的3个问题
    使用jQuery封装实用函数
    Web Fundamentsals学习1-Multiple-Screen-Site
    安装Git
    学会使用Git创建分支
  • 原文地址:https://www.cnblogs.com/proverbs/p/2852191.html
Copyright © 2011-2022 走看看