http://poj.org/problem?id=2175

Evacuation Plan
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 3256   Accepted: 855   Special Judge

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 capacity
in 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
-3 3 5
-2 -2 6
2 2 5
-1 1 3
1 1 4
-2 -2 7
0 -1 3
3 1 1 0
0 0 6 0
0 3 0 2

Sample Output

SUBOPTIMAL
3 0 1 1
0 0 6 0
0 4 0 1

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)的更多相关文章

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

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

  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(消圈)

    POJ \(Description\) \(n\)个建筑物,每个建筑物里有\(a_i\)个人:\(m\)个避难所,每个避难所可以容纳\(b_i\)个人. 给出每个建筑物及避难所的坐标,任意两点间的距离 ...

  4. POJ-2175 Evacuation Plan 最小费用流、负环判定

    题意:给定一个最小费用流的模型,根据给定的数据判定是否为最优解,如果不为最优解则给出一个比给定更优的解即可.不需要得出最优解. 解法:由给定的数据能够得出一个残图,且这个图满足了最大流的性质,判定一个 ...

  5. Codeforces Gym 100002 E "Evacuation Plan" 费用流

    "Evacuation Plan" Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/10 ...

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

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

  7. 最小费用流判负环消圈算法(poj2175)

    Evacuation Plan Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 3384   Accepted: 888   ...

  8. POJ 3680 Intervals(费用流+负权优化)

    [题目链接] http://poj.org/problem?id=3680 [题目大意] 有N个带权重的区间,现在要从中选取一些区间, 要求任意点都不被超过K个区间所覆盖,请最大化总的区间权重. [题 ...

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

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

随机推荐

  1. IKAnalyzer原理分析

    IKAnalyzer原理分析 IKAnalyzer自带的 void org.wltea.analyzer.dic.Dictionary.disableWords(Collection<Strin ...

  2. HTML5与APP的交互

    phonegap框架,html5直接用于移动开发的框架.现版本UI延迟据说还是略大. App中搞活动,每次都通过mobile api把url给app即可. App操作Html webview.load ...

  3. python中关于list列表的增删查改操作

    python中list的操#python创建列表的时候,会以堆栈的形式存放数据,从右向左往堆栈中存放数据 movies=["The holy Grail","The li ...

  4. JSP学习笔记(1)

    JSP本质就是一个servlet,当第一次接受到客户端请求时会被编译成对应的servlet,且对应的每个servlet在容器中只要一个实例. 1.1.JSP注释 <%-- JSP注释部分 --& ...

  5. SQL Server 分组后取Top N

    SQL Server 分组后取Top N(转) 近日,工作中突遇一需求:将一数据表分组,而后取出每组内按一定规则排列的前N条数据.乍想来,这本是寻常查询,无甚难处.可提笔写来,终究是困住了笔者好一会儿 ...

  6. CactiEZ 中文版V10.1安装使用以及139邮箱短信报警设置

    说明:CactiEZ中文版V10.1是基于CentOS 6.0系统,整合Cacti等相关软件,重新编译而成的一个操作系统!   说明:CactiEZ中文版V10.1是基于CentOS 6.0系统,整合 ...

  7. 重置MySQL的root用户密码(Window)

    1.首先要停止Mysql服务.打开CMD,键入命令 net stop mysql 默认的mysql服务名就是mysql,如果你修改过服务名,请自行对照修改命令. 2.在CMD中进入mysql的bin目 ...

  8. 中文man帮助安装

    下面我们来安装下中文man帮助 首先在http://pkgs.fedoraproject.org/repo/pkgs/man-pages-zh-CN/manpages-zh-1.5.2.tar.bz2 ...

  9. Spring4.0学习笔记(3) —— Spring_Bean之间的关系

    1.继承关系 bean-relation.xml <?xml version="1.0" encoding="UTF-8"?> <beans ...

  10. Box model小心得

    最近在研究css~当设置一个元素width后~有时候也会对他设定padding,margin,border值, 每次这样我就心里琢磨,那这个元素的width会变吗,js获取元素的宽度width()指的 ...