题意抽象出来就是给了一个费用流的残存网络,判断该方案是不是最优方案,如果不是,还要求给出一个更优方案。

在给定残存网络上检查是否存在负环即可判断是否最优。

沿负环增广一轮即可得到更优方案。

考虑到制作模板的需要,我用前向星建图做的。此题用邻接矩阵应该更方便。

#include<queue>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
const int MAXN=;
int nbuild,nshelt;
int x[maxn],y[maxn];
int tot,S,T;
int pointer[maxn];
int toT[MAXN];
int flo[maxn][maxn];
const int INF=0x3f3f3f;
int dis[maxn],pre[maxn],in[maxn],use[maxn];
bool vis[maxn];
bool visit[maxn];
struct Edge
{
int to,next,cap,f,w;
Edge() {};
Edge(int b,int c,int nxt,int flow,int weight) {to=b,cap=c,next=nxt,f=flow,w=weight;}
}edge[MAXN];
inline void addedge(int a,int b,int c,int flow,int w1)
{
edge[tot]=Edge(b,c,pointer[a],flow,w1);
pointer[a]=tot++;
edge[tot]=Edge(a,,pointer[b],-flow,-w1);
pointer[b]=tot++;
}
inline int cost(int a,int b)
{
return abs(x[a]-x[b])+abs(y[a]-y[b])+;
}
void init()
{
int t;
memset(pointer,-,sizeof(pointer));
memset(visit,,sizeof(vis));
tot=;
S=;T=nbuild+nshelt+;
rep(i,,nbuild)
{
scanf("%d%d%d",&x[i],&y[i],&t);
addedge(S,i,t,t,);
}
rep(i,nbuild+,nbuild+nshelt)
{
scanf("%d%d%d",&x[i],&y[i],&t);
toT[i]=tot;
addedge(i,T,t,,); }
int aedge;
rep(i,,nbuild)
{
rep(j,,nshelt)
{
scanf("%d",&t);
addedge(i,nbuild+j,INF,t,cost(i,nbuild+j));
// printf("%d-->%d w=%d\n",i,nbuild+j,cost(i,nbuild+j));
flo[i][j]=t;
aedge=toT[nbuild+j];
edge[aedge].f+=t;
edge[aedge^].f-=t;
}
} }
int ve=;
void clearcircle()
{
memset(use,,sizeof(use));
int enter;
while()
{
use[ve]++;
// printf("ve=%d\n",ve);
if(use[ve]>=) {enter=ve;break;}
ve=edge[pre[ve]^].to;
}
int sub;
do
{
sub=edge[pre[ve]^].to;
edge[pre[ve]].f+=;
edge[pre[ve]^].f-=;
ve=sub;
}while(ve!=enter);
rep(i,,nbuild)
{
for(int j=pointer[i];j!=-;j=edge[j].next)
{
int v=edge[j].to; if(v>nbuild) flo[i][v-nbuild]=edge[j].f;
}
} }
int searchcircle(int s)
{
queue<int> q;
rep(i,S,T)
{
dis[i]=INF;
vis[i]=;
pre[i]=-;
in[i]=;
}
q.push(s);
vis[s]=;
in[s]++;dis[s]=;
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=;
// printf("%d dis[u]=%d\n",u,dis[u]);
for(int j=pointer[u];j!=-;j=edge[j].next)
{
int v=edge[j].to;
// printf("%d-->%d vis[v]=%d dis[v]=%d ds[u]=%d edge[j].w=%d\n",u,v,vis[v],dis[v],dis[u],edge[j].w);
if(edge[j].cap-edge[j].f&&dis[v]>dis[u]+edge[j].w)
{
dis[v]=dis[u]+edge[j].w;
pre[v]=j;
// printf("%d-->%d vis[v]=%d dis[v]=%d ds[u]=%d edge[j].w=%d\n",u,v,vis[v],dis[v],dis[u],edge[j].w);
if(!vis[v])
{
vis[v]=;
visit[v]=;
in[v]++;
q.push(v);
if(in[v]>=T)
{
ve=v;
return ;
}
}
}
}
}
return ; }
int main()
{
// freopen("in.txt","r",stdin);
while(scanf("%d",&nbuild)==)
{
scanf("%d",&nshelt);
init();
/*rep(i,1,nbuild)
{
rep(j,1,nshelt) printf("%d ",flo[i][j]);
printf("\n");
}
rep(i,1,nbuild)
{
rep(j,1,nshelt) printf("%d ",cost(i,nbuild+j));
printf("\n");
}*/
int flag=;
ve=;
rep(i,S,T)
{
if(visit[i]) continue;
ve=searchcircle(i);
if(ve)
{
flag=;
printf("SUBOPTIMAL\n");
clearcircle();
rep(i,,nbuild)
{
rep(j,,nshelt) printf("%d ",flo[i][j]);
printf("\n");
}
break;
}
}
if(!flag) printf("OPTIMAL\n"); }
return ;
}

poj 2175 费用流消圈的更多相关文章

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

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

  2. poj2175费用流消圈算法

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

  3. POJ.2175.Evacuation Plan(消圈)

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

  4. POJ 2175 spfa费用流消圈

    题意:给出n栋房子位置和每栋房子里面的人数,m个避难所位置和每个避难所可容纳人数.然后给出一个方案,判断该方案是否最优,如果不是求出一个更优的方案. 思路:很容易想到用最小费用流求出最优时间,在与原方 ...

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

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

  6. poj 2516 (费用流)

    题意:有N个供应商,M个店主,K种物品.每个供应商对每种物品的的供应量已知,每个店主对每种物品的需求量的已知,从不同的供应商运送不同的货物到不同的店主手上需要不同的花费,又已知从供应商m送第k种货物的 ...

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

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

  8. Going Home POJ - 2195 费用流板子题

    On a grid map there are n little men and n houses. In each unit time, every little man can move one ...

  9. poj 3422 (费用流)

    从左上角到有下角k次能获得的最大值. 跟hdu 2686一样的题目,这题一个点可以重复走,只能得到一次值. #include<stdio.h> #include<string.h&g ...

随机推荐

  1. python的数据类型--list和tuple

    list是Python的一种数据类型,是一个有序的集合,可以随时添加和删除.写法为list名称+[] list[]内的元素不仅仅为str,可以是数字,布尔值. 访问方法为变量名或者变量[索引],和C的 ...

  2. 【转】Vue-详解设置路由导航的两种方法: <router-link :to="..."> 和router.push(...)

    一.<router-link :to="..."> to里的值可以是一个字符串路径,或者一个描述地址的对象.例如: // 字符串 <router-link to= ...

  3. SecureCRT sftp上传文件报错:put: failed to upload xxx 拒绝访问

    1.问题 使用sftp上传文件时报错:put: failed to upload xxx 拒绝访问.类似下图所示: 2.原因 造成这个问题的原因可能有两个,一是要上到的那个目录剩余磁盘空间不足,二是打 ...

  4. Flexbox 布局的最简单表单 (转)

    作者: 阮一峰 弹性布局(Flexbox)逐渐流行,越来越多人使用,因为它写 CSS 布局真是太方便了. 三年前,我写过 Flexbox 的介绍(上,下),但是有些地方写得不清楚.今天,我看到一篇教程 ...

  5. Spring @Scheduled @Async联合实现调度任务(2017.11.28更新)

    定时任务之前一直用的是quartz之类,但是注意到Spring中其实也提供了一种简单的调度注释@Scheduled,也就想尝一下鲜.. 代码示意如下: @Component @EnableSchedu ...

  6. mex

    edit(fullfile(prefdir, 'mexopts.bat')) http://www.mathworks.cn/support/solutions/en/data/1-8FJXQE/in ...

  7. PAT-GPLT训练集 L1-043 阅览室

    PAT-GPLT训练集 L1-043 阅览室 注意:连续的S和E才算一次借还 代码: #include<iostream> #include<cstdio> using nam ...

  8. win7 php nginx 启动命令

    1 php 启动命令 @echo off e: cd E:/php-/ echo "php is starting on port 9007, php_version is 7.0.6&qu ...

  9. mv

    mv命令是move的缩写,可以用来移动文件或者将文件改名,这也是个常用命令,经常用来备份文件或者目录. 1.命令格式: mv  [选项] 源文件或目录  目标文件或目录 2.命令功能: 视mv命令中第 ...

  10. cocos2d方块方块

    cGridSize=32 cSceneWidth=8+2 cSceneHeight=18 fuction Grid2Pos(x,y) local visibleSize=cc.Director:get ...