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. nyoj 76

    #include <iostream> using namespace std; int main() { int i,t,n; int a[101]; cin>>t; whi ...

  2. JQuery图片轮换 nivoSlider图片轮换

    效果图: 第一步:添加引用 <script src="jquery-ui-1.9.2.custom.min.js" type="text/javascript&qu ...

  3. Android--------使用gson解析json文件

    ##使用gson解析json文件 **json的格式有两种:** **1. {}类型,及数据用{}包含:** **2. []类型,即数据用[]包含:** 下面用个例子,简单的介绍gson如何解析jso ...

  4. android 检查网络是否可用,如果不可用弹出设置,让用户改变

    /** * 校验网络,如果没有网络,返回true * * @return boolean */ @Override public boolean hasInternetConnected() { Co ...

  5. 认识html标签

    让我们通过一个网页的学习,来对html标签有一个初步理解. 平常大家说的上网就是浏览各种各式各样的网页,这些网页都是由html标签组成的. 下面就是一个简单的网页.效果图如下: 我们来分析一下,这个网 ...

  6. PHP 运算符

    本章节我们将讨论 PHP 中不同运算符的应用. 在 PHP 中,赋值运算符 = 用于给变量赋值. 在 PHP 中,算术运算符 + 用于把值加在一起. PHP 算术运算符 运算符 名称 描述 实例 结果 ...

  7. JAVA-3-水仙花

    public static void main(String[] args) { // TODO 自动生成的方法存根 int i = 100; while (i < 1000) { int a, ...

  8. html5之web worker

    Web Worker   在本文中 与 Web Worker 进行双向通信 WindowTimers 在 IE10 Platform Preview 4 中对 Web Worker 的更新 API 参 ...

  9. dede仿站笔记

    仿站步骤查看是否为dedecms的方法,看引用路径src="/templets/default2012/images/toutiao.png" 0查看仿站编码,选择utf8或gbk ...

  10. 网址测速JS

    /*.route_nav li a:hover{background: #3c7f84 url(title.png) no-repeat;border-color:#84a3a5;}*/ .route ...