鸣谢: http://www.cppblog.com/y346491470/articles/152317.html

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

【题解】:好明显的费用流(距离看成费用),如果此题建费用流模型找最小费用流必定超时,而且题目不需要我们找到最优方案。
              定理:一个费用流是最小费用流的充要条件是这个费用流的残量网络没有负费用环
              由这个定理,我们只需判断当前方案是否有负费用圈,没有即意味着当前方案为最优方案。
              如果有的话,此时只需沿着负费用圈把各边流量增加1,增流之后残量网络对应的方案肯定是一个更优方案(很容易证明)。

SPFA找负环: 某个点进入队列大于等于nodes次证明存在负环。(nodes一般情况是顶点个数,这道题给图很特殊,取max{n,m}就可以)

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn = ;
const int maxe = ;
const int maxdist = <<;
const int maxf = <<;
struct edge{
int u,v,c,cost;
edge(int e1=,int e2=,int e3=,int e4=){ u=e1; v=e2; c=e3; cost=e4; }
}e[maxe];
int cnt;
int head[maxn];
int next[maxe];
void add(int u,int v,int c,int w,int f){
e[cnt] = edge(u,v,c-f,w);
next[cnt]=head[u], head[u] = cnt++;
e[cnt] = edge(v,u,f,-w);
next[cnt]=head[v], head[v] = cnt++;
}
int source,sink,nodes;
int spfa(){
queue<int> que;
que.push(sink);
int dist[maxn],inque[maxn],visits[maxn],pre[maxn];
for(int i=;i<=nodes;i++)
dist[i]=maxdist,inque[i]=,visits[i]=,pre[i]=-;
int u,v,neg_loop=;
dist[sink]=;
while(!que.empty()){
u=que.front(); que.pop(); inque[u]=;
visits[u]++;
if(visits[u] > nodes) { //产生了负环
neg_loop=; break;
}
//printf("u = %d, visits[u] = %d\n",u,visits[u]);
for(int i=head[u];i>=;i=next[i])
if(e[i].c && dist[e[i].v] > dist[u]+e[i].cost){
v=e[i].v;
dist[v] = dist[u]+e[i].cost;
if(!inque[v])
que.push(v), inque[v]=;
pre[v]=i;
} }
int visited[maxn]={},i;
if(neg_loop){
int counter=nodes; //负环长肯定不超过顶点数,而抛出负环的点不一定在负环中
while(counter--)
u=e[pre[u]].u;
while(!visited[u]){
i=pre[u],visited[u]++,e[i].c--,e[i^].c++;
//printf("u = %d, i = %d, %d --> %d\n",u,i,e[i].u,e[i].v);
u=e[i].u;
}
}
return neg_loop;
}
void initial(){
cnt = ;
memset(head,-,sizeof(head));
//initial source,sink and nodes;
}
struct pos{
int x,y;
}building[],shelter[];
int getdist(pos &s,pos &t){
int ret=s.x-t.x;
if(ret < ) ret=-ret;
if(s.y > t.y) ret+=s.y-t.y;
else ret+=t.y-s.y;
ret++;
return ret;
}
int bi[],si[],dist[][],plan[][];
int main()
{
int n,m;
while(scanf("%d%d",&n,&m) != EOF){
for(int i=;i<=n;i++)
scanf("%d%d%d",&building[i].x,&building[i].y,&bi[i]);
for(int i=;i<=m;i++)
scanf("%d%d%d",&shelter[i].x,&shelter[i].y,&si[i]);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
dist[i][j]=getdist(building[i],shelter[j]);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
scanf("%d",&plan[i][j]);
int flag=;
//****************************************//
for(int i=;i<=n;i++) plan[i][]=;
for(int j=;j<=m;j++) plan[][j]=;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
plan[i][]+=plan[i][j],plan[][j]+=plan[i][j];
for(int i=;i<=n;i++)
if(plan[i][] != bi[i])
flag=;
for(int j=;j<=m;j++)
if(plan[][j] > si[j])
flag=;
//****************************************//一些额外的判断
initial();
source=,sink=n+m+,nodes=sink+;
for(int i=;i<=n;i++) add(source,i,bi[i],,bi[i]);
for(int j=;j<=m;j++) add(n+j,sink,si[j],,plan[][j]);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
add(i,j+n,bi[i],dist[i][j],plan[i][j]);
if(!flag)
flag = spfa();
if(!flag) printf("OPTIMAL\n");
else {
printf("SUBOPTIMAL\n");
memset(plan,,sizeof(plan));
for(int u=,v;u<=n;u++)
for(int i=head[u];i>=;i=next[i]){
v=e[i].v;
if(v > n) v -= n;
plan[u][v] += e[i^].c;
}
for(int i=;i<=n;i++){
for(int j=;j<m;j++) printf("%d ",plan[i][j]);
printf("%d\n",plan[i][m]);
}
}
}
return ;
}

poj2175的更多相关文章

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

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

  2. POJ2175 Evacuation Plan

    Evacuation Plan Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4617   Accepted: 1218   ...

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

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

  4. POJ2175:Evacuation Plan(消负圈)

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

  5. poj2175费用流消圈算法

    题意:      有n个建筑,每个建筑有ai个人,有m个避难所,每个避难所的容量是bi,ai到bi的费用是|x1-x2|+|y1-y2|+1,然后给你一个n*m的矩阵,表示当前方案,问当前避难方案是否 ...

  6. OJ题目分类

    POJ题目分类 | POJ题目分类 | HDU题目分类 | ZOJ题目分类 | SOJ题目分类 | HOJ题目分类 | FOJ题目分类 | 模拟题: POJ1006 POJ1008 POJ1013 P ...

随机推荐

  1. How to set custom JsonSerializerSettings for Json.NET in MVC 4 Web API?

    ou can customize the JsonSerializerSettings by using theFormatters.JsonFormatter.SerializerSettings  ...

  2. Java 可中断线程

    PART.1 无法中断的线程 一个无法中断的线程的例子. public class UninterruptableThread { @SuppressWarnings("deprecatio ...

  3. 有关Repeater的事件

    Repeater放在Updatepanel中是可以通过右键->属性,双击事件来生成事件的,若能这样的话,那最后是用这种方法吧,最起码不会出错!

  4. asp.net 使用HttpModule记录全局错误

    以前使用Global.asax记录全局的错误日志觉得挺好用,但是如果一个解决方案下有N多个项目,每个下边都需要加一个并且代码都还是重复的,终于有一天无法再忍受这种模式,考虑到HttpModule,直接 ...

  5. java:添加一条数据到数据库中文乱码

    在数据库链接地址后面加上:characterEncoding=UTF8 如:jdbc\:mysql\://localhost\:3306/db_sjzdaj?relaxAutoCommit=true& ...

  6. 在Linux下如何用Shell脚本读写XML?现有一个config.xml(转)

    在Linux下如何用Shell脚本读写XML?现有一个config.xml <?xml version="1.0" encoding="UTF-8"?&g ...

  7. poj2891--扩展欧几里德算法

    /* 该题使用的是扩展欧几里德算法,求模线性同余方程: 分析题目:以题目输出结果为例 ,要求得到一个整数X可以满足 X % a = r,a,r,为数组名: 设数组元素为两个时, 列出方程:X % a1 ...

  8. leetcode 4sum python

    class Solution(object): def fourSum(self, nums, target): """ :type nums: List[int] :t ...

  9. CSS超链接-光标-缩放

    CSS超链接-光标-缩放 1.CSS 中链接的使用2.CSS 中光标的使用3.CSS 中缩放的使用 1.CSS 中链接的使用超链接伪类属性a:link    表示该超链接文字尚未被点选a:visite ...

  10. 《转》读discuzx3.1 数据库层笔记

    最近开始在看discuzx3.1的代码,看到数据库层的实现,discuzx的数据库层能够支撑数据库分库,分布式部署,主要水平分表,也可以很方便的支持其他数据库.性能上,可以做读写分离,支持数据缓存.可 ...