POJ


\(Description\)

\(n\)个建筑物,每个建筑物里有\(a_i\)个人;\(m\)个避难所,每个避难所可以容纳\(b_i\)个人。

给出每个建筑物及避难所的坐标,任意两点间的距离为它们的曼哈顿距离\(+1\)。

现在给出一个分配方案(\(g[i][j]\)表示第\(i\)个建筑物去第\(j\)个避难所的人数),问是否存在所有人移动的距离之和比当前更小的方案。如果存在,输出任意一组更小的方案。

\(n,m\leq100\)

\(Solution\)

直接跑费用流会T,但是也没必要。

如果残量网络存在负环(只走有流量的边),那么沿该负环继续增广,可以得到一组更优的解。否则就是当前流量下的最小费用流。

所以建出残量网络,找出负环来,在负环上走一遍就行了。

\(S\to i\)的每条边的流量肯定是流满的,所以不需要建(\(i'\to T\)的就不一定了)。

复杂度\(O(nm)\)。(\(m\)是边数)


//688K	329MS
#include <queue>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define gc() getchar()
typedef long long LL;
const int N=205,M=(105*105+N)*2,INF=0x3f3f3f3f; int Enum,H[N],nxt[M],to[M],cost[M],dis[N],pre[N],g[105][105]; inline int read()
{
int now=0,f=1;register char c=gc();
for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now*f;
}
inline void AE(int u,int v,int w,int c)
{
if(w) to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum, cost[Enum]=c;
}
int SPFA(const int n)
{
static int tm[N];
static bool inq[N];
std::queue<int> q;
memset(dis,0x3f,n+1<<2);
dis[n]=0, q.push(n), tm[n]=1;
while(!q.empty())
{
int x=q.front(); q.pop();
inq[x]=0;
for(int i=H[x],v; i; i=nxt[i])
if(dis[to[i]]>dis[x]+cost[i])
{
dis[v=to[i]]=dis[x]+cost[i], pre[v]=x;
if(!inq[v])
{
if(++tm[v]>=n) return v;
q.push(v), inq[v]=1;
}
}
}
return -1;
}
void FindCircle(int x,const int n)
{
static bool vis[N];
while(!vis[x]) vis[x]=1, x=pre[x];//p不一定在环上(但是能回到环),应该先找出来啊。。
int tmp=x;
do
{
int v=pre[x];//v->x
if(x<=n && v>n) --g[x][v-n];
else if(x>n && v<=n) ++g[v][x-n];
x=v;
}while(x!=tmp);
} int main()
{
static int a[N],b[N],c[N],d[N],cap[N],use[N];
const int n=read(),m=read(),T=n+m+1;
for(int i=1; i<=n; ++i) a[i]=read(),b[i]=read(),read();
for(int i=1; i<=m; ++i) c[i]=read(),d[i]=read(),cap[i]=read();
for(int i=1; i<=n; ++i)
for(int j=1; j<=m; ++j)
{
use[j]+=g[i][j]=read();
int cost=std::abs(a[i]-c[j])+std::abs(b[i]-d[j])+1;
AE(i,j+n,INF-g[i][j],cost), AE(j+n,i,g[i][j],-cost);//negative!
}
for(int i=1; i<=m; ++i) AE(i+n,T,cap[i]-use[i],0), AE(T,i+n,use[i],0);
int p=SPFA(T);
if(p==-1) puts("OPTIMAL");
else
{
FindCircle(p,n), puts("SUBOPTIMAL");
for(int i=1; i<=n; ++i,putchar('\n'))
for(int j=1; j<=m; ++j) printf("%d ",g[i][j]);
} return 0;
}

POJ.2175.Evacuation Plan(消圈)的更多相关文章

  1. POJ 2175 Evacuation Plan (费用流,负环,消圈法,SPFA)

    http://poj.org/problem?id=2175 Evacuation Plan Time Limit: 1000MS   Memory Limit: 65536K Total Submi ...

  2. POJ 2175 Evacuation Plan

    Evacuation Plan Time Limit: 1000ms Memory Limit: 65536KB This problem will be judged on PKU. Origina ...

  3. poj 2175 Evacuation Plan 最小费用流判定,消圈算法

    题目链接 题意:一个城市有n座行政楼和m座避难所,现发生核战,要求将避难所中的人员全部安置到避难所中,每个人转移的费用为两座楼之间的曼哈顿距离+1,题目给了一种方案,问是否为最优方案,即是否全部的人员 ...

  4. POJ - 2175 Evacuation Plan (最小费用流消圈)

    题意:有N栋楼,每栋楼有\(val_i\)个人要避难,现在有M个避难所,每个避难所的容量为\(cap_i\),每个人从楼i到避难所j的话费是两者的曼哈顿距离.现在给出解决方案,问这个解决方案是否是花费 ...

  5. POJ 2175 Evacuation Plan 费用流 负圈定理

    题目给了一个满足最大流的残量网络,判断是否费用最小. 如果残量网络中存在费用负圈,那么不是最优,在这个圈上增广,增广1的流量就行了. 1.SPFA中某个点入队超过n次,说明存在负环,但是这个点不一定在 ...

  6. poj 2175 费用流消圈

    题意抽象出来就是给了一个费用流的残存网络,判断该方案是不是最优方案,如果不是,还要求给出一个更优方案. 在给定残存网络上检查是否存在负环即可判断是否最优. 沿负环增广一轮即可得到更优方案. 考虑到制作 ...

  7. POJ 2157 Evacuation Plan [最小费用最大流][消圈算法]

    ---恢复内容开始--- 题意略. 这题在poj直接求最小费用会超时,但是题意也没说要求最优解. 根据线圈定理,如果一个跑完最费用流的残余网络中存在负权环,那么顺着这个负权环跑流量为1那么会得到更小的 ...

  8. POJ 2175:Evacuation Plan(费用流消圈算法)***

    http://poj.org/problem?id=2175 题意:有n个楼,m个防空洞,每个楼有一个坐标和一个人数B,每个防空洞有一个坐标和容纳量C,从楼到防空洞需要的时间是其曼哈顿距离+1,现在给 ...

  9. POJ2175:Evacuation Plan(消负圈)

    Evacuation Plan Time Limit: 1000MSMemory Limit: 65536KTotal Submissions: 5665Accepted: 1481Special J ...

随机推荐

  1. lightoj1336 约数和

    /*sigma(n)的每一项都可以看成是个pi的[0,ei]等比数列求和公式,那么sigma(n)就是n所有正约数的和要求找到sigma(x)为奇数的个数1<=x<=n */ 看题解的.. ...

  2. cf861D 字典树+时间戳

    好久没碰字典树之类的题了,搞起来有点生疏 /* 把所有母串的后缀加入字典树中 然后再扫一次所有母串的后缀,把后缀放到字典树中查询,找到第一个访问次数为1的结点返回即可 num在计数时,同一个母串的子串 ...

  3. WBXML 1.3协议摘要

    协议地址:WAP195   网络字节顺序:big-endian.   为什么要加0x40? 参考:Compressing XML When an element contains content (t ...

  4. 在Ubuntu下创建一个新的用户

    Step1:添加新用户useradd -r -m -s /bin/bash 用户名 Step2:配置新用户密码passwd 用户名 Step3:给新添加的用户增加ROOT权限vim /etc/sudo ...

  5. win10远程桌面出现身份验证错误。要求的函数不受支持

    打开组策略,依次展开“计算机配置”->“管理模板”->“系统”->“凭据分配”,设置名称: “加密 Oracle 修正” 为已启用,并设置保护级别为“易受攻击”

  6. Unable to locate package python-pip

    原文:https://blog.csdn.net/yyinhai/article/details/53056973 Ubuntu下执行apt install python-pip得到如下错误提示: R ...

  7. python-中缀表达式转前缀表达式

    作完了中缀前缀,作一个归纳吧. https://www.cnblogs.com/unixfy/p/3344550.html # coding = utf-8 class Stack: def __in ...

  8. java使用Jsch实现远程操作linux服务器进行文件上传、下载,删除和显示目录信息

    1.java使用Jsch实现远程操作linux服务器进行文件上传.下载,删除和显示目录信息. 参考链接:https://www.cnblogs.com/longyg/archive/2012/06/2 ...

  9. SpringBoot学习(3)-SpringBoot添加支持CORS跨域访问

    SpringBoot学习(3)-SpringBoot添加支持CORS跨域访问 https://blog.csdn.net/yft_android/article/details/80307672

  10. 为tomcat8安装Native library

    安装依赖包 yum install -y cmake gcc expat-devel perl wget 安装apr wget http://mirrors.hust.edu.cn/apache//a ...