POJ 2175 Evacuation Plan (费用流,负环,消圈法,SPFA)
http://poj.org/problem?id=2175
|
Evacuation Plan
Description The City has a number of municipal buildings and a number of fallout shelters that were build specially to hide municipal workers in case of a nuclear war. Each fallout shelter has a limited capacityin terms of a number of people it can accommodate, and there's almost no excess capacity in The City's fallout shelters. Ideally, all workers from a given municipal building shall run to the nearest fallout shelter. However, this will lead to overcrowding of some fallout shelters, while others will be half-empty at the same time. To address this problem, The City Council has developed a special evacuation plan. Instead of assigning every worker to a fallout shelter individually (which will be a huge amount of information to keep), they allocated fallout shelters to municipal buildings, listing the number of workers from every building that shall use a given fallout shelter, and left the task of individual assignments to the buildings' management. The plan takes into account a number of workers in every building - all of them are assigned to fallout shelters, and a limited capacity of each fallout shelter - every fallout shelter is assigned to no more workers then it can accommodate, though some fallout shelters may be not used completely. The City Council claims that their evacuation plan is optimal, in the sense that it minimizes the total time to reach fallout shelters for all workers in The City, which is the sum for all workers of the time to go from the worker's municipal building to the fallout shelter assigned to this worker. The City Mayor, well known for his constant confrontation with The City Council, does not buy their claim and hires you as an independent consultant to verify the evacuation plan. Your task is to either ensure that the evacuation plan is indeed optimal, or to prove otherwise by presenting another evacuation plan with the smaller total time to reach fallout shelters, thus clearly exposing The City Council's incompetence. During initial requirements gathering phase of your project, you have found that The City is represented by a rectangular grid. The location of municipal buildings and fallout shelters is specified by two integer numbers and the time to go between municipal building at the location (Xi, Yi) and the fallout shelter at the location (Pj, Qj) is Di,j = |Xi - Pj| + |Yi - Qj| + 1 minutes. Input
The input consists of The City description and the evacuation plan description. The first line of the input file consists of two numbers N and M separated by a space. N (1 ≤ N ≤ 100) is a number of municipal buildings in The City (all municipal buildings are
numbered from 1 to N). M (1 ≤ M ≤ 100) is a number of fallout shelters in The City (all fallout shelters are numbered from 1 to M). The following N lines describe municipal buildings. Each line contains there integer numbers Xi, Yi, and Bi separated by spaces, where Xi, Yi (-1000 ≤ Xi, Yi ≤ 1000) are the coordinates of the building, and Bi (1 ≤ Bi ≤ 1000) is the number of workers in this building. The description of municipal buildings is followed by M lines that describe fallout shelters. Each line contains three integer numbers Pj, Qj, and Cj separated by spaces, where Pi, Qi (-1000 ≤ Pj, Qj ≤ 1000) are the coordinates of the fallout shelter, and Cj (1 ≤ Cj ≤ 1000) is the capacity of this shelter. The description of The City Council's evacuation plan follows on the next N lines. Each line represents an evacuation plan for a single building (in the order they are given in The City description). The evacuation plan of ith municipal building consists of M integer numbers Ei,j separated by spaces. Ei,j (0 ≤ Ei,j ≤ 1000) is a number of workers that shall evacuate from the ith municipal building to the jth fallout shelter. The plan in the input file is guaranteed to be valid. Namely, it calls for an evacuation of the exact number of workers that are actually working in any given municipal building according to The City description and does not exceed the capacity of any given fallout shelter. Output
If The City Council's plan is optimal, then write to the output the single word OPTIMAL. Otherwise, write the word SUBOPTIMAL on the first line, followed by N lines that describe your plan in the same format as in the input file. Your plan need not be optimal
itself, but must be valid and better than The City Council's one. Sample Input 3 4 Sample Output SUBOPTIMAL Source |
||||||||||
题意:
有N幢楼,M个避难所。给出坐标,楼中人数及避难所容量,每人从楼到避难所的花费是曼哈顿距离+1。
现给出一种避难方案,推断是否是最优的(全部人的花费之和最小),假设不是,给出一种更优的方案。
分析:
非常easy想到是费用流。
源点到楼连边。容量为楼中人数。单位流量费用为0;避难所到汇点连边,容量为避难所容量。单位流量费用为0;楼到避难所连边,容量为无穷大,单位流量费用为曼哈顿距离+1。
在此图中跑一遍最小费用最大流,假设最小费用比给出的方案费用小,则相应的流的方案更优(且是最优的)。
上述思路尽管没错,但非常不幸,效率非常低,我毫无疑问地获得了TLE。那么有没有更好的算法呢?
按最小费用最大流跑出的流相应最优的方案,那么已经给出的方案显然相应某个最大流,题目要求推断给出的方案是否是最优的<=>该流的费用最小。假设某流f是最小费用流<=>残留网络中没有负圈。假设有负圈。则沿着该负圈增广。就能得到同样流量下费用更小的流。推断负圈仅仅要用SPFA,在实际測试中,用栈比队列推断负圈效率更高。值得注意的是,假设某个点进栈/队N次(假设一共N个点)。那么图中存在负环,可是这个点却未必在负环中(是不是非常惊悚?)。仅仅能说这个点被负环更新过。即负环在这个点之前,所以我们仅仅要从这个点往前找到负环。然后在负环中增广,就可以获得费用更小的流。
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<ctime>
#include<cctype>
#include<cmath>
#include<string>
#include<cstring>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<map>
#include<set>
#define sqr(x) ((x)*(x))
#define LL long long
#define itn int
#define INF 0x3f3f3f3f
#define PI 3.1415926535897932384626
#define eps 1e-10
#define maxm (65536)
#define maxn (202) using namespace std; struct __point
{
int x,y,p;
}b[101],sh[101];
int n,m; int fir[maxn];
int u[maxm],v[maxm],cap[maxm],flow[maxm],cost[maxm],nex[maxm];
int e_max;
int q[maxn],d[maxn],prev[maxn],cnt[maxn];
bool inq[maxn]; int G[101][101];
int shelter[101];
bool vis[maxn]; void add_edge(int _u,int _v,int _cap,int _cost,int _f)
{
int e;
e=e_max++;
u[e]=_u;v[e]=_v;cap[e]=_cap;cost[e]=_cost;flow[e]=_f;
nex[e]=fir[u[e]];fir[u[e]]=e;
e=e_max++;
u[e]=_v;v[e]=_u;cap[e]=0;cost[e]=-_cost;flow[e]=-_f;
nex[e]=fir[u[e]];fir[u[e]]=e;
} int negative_loop(int s,int t)
{
int f,r,top=-1;
f=0;r=-1; memset(cnt,0,sizeof cnt);
memset(d,0,sizeof d);
memset(inq,1,sizeof inq);//inq是bool类型的数组,每一个元素占1字节,所以能够这样
memset(prev,-1,sizeof prev);
for (int i=s;i<=t;i++)
q[++r]=i; while (f<=r)
{
int x=q[r--];//栈式写法。r--改成f++就是队列了。队列要将数组扩大。
inq[x]=false;
for (int e=fir[x];~e;e=nex[e])
{
if (cap[e]>flow[e] && d[v[e]]>d[u[e]]+cost[e])
{
d[v[e]]=d[u[e]]+cost[e];
prev[v[e]]=e;
if (!inq[v[e]])
{
q[++r]=v[e];
inq[v[e]]=true;
cnt[v[e]]++;
if (cnt[v[e]]>t-s+1) return v[e];
//如过不想推断边界。就把这个值调大些,由于假设没有负环就不会进队/栈那么多次,假设有负环,就会无限循环下去
}
}
}
} return -1;
} inline int __cost(const __point &p1,const __point &p2)
{
return abs(p1.x-p2.x)+abs(p1.y-p2.y)+1;
} int main()
{
#ifndef ONLINE_JUDGE
freopen("/home/fcbruce/文档/code/t","r",stdin);
#endif // ONLINE_JUDGE int p;
int s,t;
scanf("%d%d",&n,&m);
s=0;t=n+m+1;
e_max=0;
memset(fir,-1,sizeof fir); for (int i=0;i<n;i++)
{
scanf("%d%d%d",&b[i].x,&b[i].y,&b[i].p);
add_edge(s,i+1,b[i].p,0,b[i].p);
} for (int i=0;i<m;i++)
{
scanf("%d%d%d",&sh[i].x,&sh[i].y,&sh[i].p);
} memset(shelter,0,sizeof shelter);
for (int i=0;i<n;i++)
{
for (int j=0;j<m;j++)
{
scanf("%d",&p);
shelter[j]+=p;
add_edge(i+1,n+j+1,INF,__cost(b[i],sh[j]),p);
}
} for (int i=0;i<m;i++)
{
add_edge(i+1+n,t,sh[i].p,0,shelter[i]);
} int k=negative_loop(s,t); if (k!=-1)
{
puts("SUBOPTIMAL");
memset(vis,0,sizeof vis); for (int e=prev[k];!vis[v[e]];e=prev[u[e]])//往前找负环
{
vis[v[e]]=true;
k=v[e];
} for (int e=prev[k];;e=prev[u[e]])//在负环中增广
{
flow[e]++;//仅仅要找一个更优的解。+1即可
flow[e^1]--;
if (u[e]==k)break;
} for (int e=0;e<e_max;e++)
{
if (u[e]>0 && u[e]<=n && v[e]>n && v[e]<=n+m)
G[u[e]-1][v[e]-n-1]=flow[e];
} for (int i=0;i<n;i++)
{
for (int j=0;j<m;j++)
{
if (j) putchar(' ');
printf("%d",G[i][j]);
}
putchar('\n');
}
}
else
puts("OPTIMAL"); return 0;
}
POJ 2175 Evacuation Plan (费用流,负环,消圈法,SPFA)的更多相关文章
- POJ 2175 Evacuation Plan 费用流 负圈定理
题目给了一个满足最大流的残量网络,判断是否费用最小. 如果残量网络中存在费用负圈,那么不是最优,在这个圈上增广,增广1的流量就行了. 1.SPFA中某个点入队超过n次,说明存在负环,但是这个点不一定在 ...
- POJ 2175 Evacuation Plan
Evacuation Plan Time Limit: 1000ms Memory Limit: 65536KB This problem will be judged on PKU. Origina ...
- POJ.2175.Evacuation Plan(消圈)
POJ \(Description\) \(n\)个建筑物,每个建筑物里有\(a_i\)个人:\(m\)个避难所,每个避难所可以容纳\(b_i\)个人. 给出每个建筑物及避难所的坐标,任意两点间的距离 ...
- POJ-2175 Evacuation Plan 最小费用流、负环判定
题意:给定一个最小费用流的模型,根据给定的数据判定是否为最优解,如果不为最优解则给出一个比给定更优的解即可.不需要得出最优解. 解法:由给定的数据能够得出一个残图,且这个图满足了最大流的性质,判定一个 ...
- Codeforces Gym 100002 E "Evacuation Plan" 费用流
"Evacuation Plan" Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/10 ...
- POJ - 2175 Evacuation Plan (最小费用流消圈)
题意:有N栋楼,每栋楼有\(val_i\)个人要避难,现在有M个避难所,每个避难所的容量为\(cap_i\),每个人从楼i到避难所j的话费是两者的曼哈顿距离.现在给出解决方案,问这个解决方案是否是花费 ...
- 最小费用流判负环消圈算法(poj2175)
Evacuation Plan Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 3384 Accepted: 888 ...
- POJ 3680 Intervals(费用流+负权优化)
[题目链接] http://poj.org/problem?id=3680 [题目大意] 有N个带权重的区间,现在要从中选取一些区间, 要求任意点都不被超过K个区间所覆盖,请最大化总的区间权重. [题 ...
- poj 2175 Evacuation Plan 最小费用流判定,消圈算法
题目链接 题意:一个城市有n座行政楼和m座避难所,现发生核战,要求将避难所中的人员全部安置到避难所中,每个人转移的费用为两座楼之间的曼哈顿距离+1,题目给了一种方案,问是否为最优方案,即是否全部的人员 ...
随机推荐
- 最近很火的携程Java 工程师的一道面向对象面试题
最近这道面试题,传遍程序员各大小园地,本小白特摘抄整理与大家一起学习: 原题: package com.gxlee; public class Base { private String baseNa ...
- PHP 杂项 函数
安装 杂项函数是 PHP 核心的组成部分.无需安装即可使用这些函数. Runtime 配置 杂项函数的行为受 php.ini 文件中的设置的影响. 杂项配置选项: 名称 默认 描述 可更改 ignor ...
- MFC 全局配置 读取保存配置
不知道关于全局配置别人都是怎么处理的,最近做的东西都用到全局配置,而且要保存软件的设置,下次启动时要使用上次关闭时的配置. 我的做法是建一个类用来保存和读取配置,并且在这个类中创建一些变量,供所有的界 ...
- 13 hbase连接
Configuration conf=new Configuration(); String zookeeper=""; String clientport="; Str ...
- Java中的HashMap和Hashtable
代码: import java.util.*; public class test{ public static void main(String[] args) { HashMap hm = new ...
- CSS分别设置Input样式(按input类型)
当你看到<input>这个html标签的时候,你会想到什么?一个文本框?一个按钮?一个单选框?一个复选框?……对,对,对,它们都对.也许你可能想不到,这个小小的input竟然可以创造出10 ...
- SQL中删除同一字段中重复的值
/////////////////////目地:ZDJZ_DIS中 name字段有重复的值,删除重复的值 DELETE * FROM ZDJZ_DIS WHERE NAME IN (select NA ...
- RequireJS学习笔记(转)
前言 进入移动前端是很不错的选择,这块也是我希望的道路,但是不熟悉啊... 现在项目用的是require+backbone,整个框架被封装了一次,今天看了代码搞不清楚,觉得应该先从源头抓起,所以再看看 ...
- FSG1.33解压缩算法分析
之前只是知道怎样脱去fsg壳,对壳的压缩算法没有太多的注意,今天就对算法进行一些分析 使用的版本是fsg1.33,首先用peid查壳: 2.将程序载入OD,看到如下代码 可以看到这段代码主要是从以es ...
- tomcat+mysql数据库连接池的操作
使用tomcat中的context.xml设置连接池 打开文件:Apache Software Foundation\Tomcat 6.0\conf\context.xml <Resource ...
The City has a number of municipal buildings and a number of fallout shelters that were build specially to hide municipal workers in case of a nuclear war. Each fallout shelter has a limited capacity