POJ2195:Going Home(费用流入门)
http://poj.org/problem?id=2195
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <math.h>
#define inf 0x3f3f3f3f
using namespace std;
int n,m,s,t,tt;
struct pointe
{
int x,y;
} l[],r[];
struct node
{
int x,y,c,w;
int next;
} eg[];
char map[][];
int head[],v[],dis[],pre[];
void init()
{
memset(head,-,sizeof(head));
tt=;
s=;
t=n*m+;
}
void add(int xx,int yy,int cc,int ww)
{
eg[tt].x=xx;
eg[tt].y=yy;
eg[tt].c=cc;
eg[tt].w=ww;
eg[tt].next=head[xx];
head[xx]=tt++;
eg[tt].x=yy;
eg[tt].y=xx;
eg[tt].c=;
eg[tt].w=-ww;
eg[tt].next=head[yy];
head[yy]=tt++;
}
int spfa(int s,int t)
{
for(int i=s; i<=t; i++)
{
v[i]=;
pre[i]=-;
dis[i]=inf;
}
queue<int>q;
dis[s]=;
q.push(s);
while(!q.empty())
{
int ff=q.front();
q.pop();
v[ff]=;
//今天算是刚了解邻接边表第一次更新的是与源点相邻的第一层
//例如head[10]->1,3,5,7....;
for(int i=head[ff]; i!=-; i=eg[i].next)
{
int w1=eg[i].y;
if(eg[i].c&&dis[w1]>dis[ff]+eg[i].w)
{
dis[w1]=dis[ff]+eg[i].w;//注意这里dis[ff]
pre[w1]=i;//算是了解么意思了
if(!v[w1])
{
v[w1]=;
q.push(w1);
}
}
}
}
if(dis[t]==inf)
{
return ;
}
return ;
}
void KM(int s,int t)
{
int ans=,minx;
while(spfa(s,t)==)
{
minx=inf;
for(int i=pre[t]; i!=-; i=pre[eg[i].x])
minx=min(minx,eg[i].c);
for(int i=pre[t]; i!=-; i=pre[eg[i].x])
{
eg[i].c-=minx;
eg[i+].c+=minx;
}
ans+=minx*dis[t];
}
cout<<ans<<endl;
return ;
}
int main()
{
int t1,t2,temp;
while(scanf("%d%d",&n,&m)!=EOF&&(n||m))
{
t1=t2=;
init();
for(int i=; i<=n; i++)
scanf("%*c%s",map[i]+);
for(int i=; i<=n; i++)
{
for(int j=; j<=m; j++)
{
temp=(i-)*m+j;
if(map[i][j]=='m')
{
add(s,temp,,);
l[t1].x=i;
l[t1++].y=j;
}
else if(map[i][j]=='H')
{
add(temp,t,,);
r[t2].x=i;
r[t2++].y=j;
}
}
}
for(int i=; i<t1; i++)
{
int l1=(l[i].x-)*m+l[i].y;
for(int j=; j<t2; j++)
{
int l2=(r[j].x-)*m+r[j].y;
int l3=abs(l[i].x-r[j].x)+abs(l[i].y-r[j].y);
add(l1,l2,,l3);
}
}
KM(s,t);
}
return ;
}
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <queue>
#include <math.h>
#define inf 0x3f3f3f3f
using namespace std;
struct node1//记录h或者m的坐标
{
int x,y;
} a[],b[];
struct node
{
int x,y,c,w;
int next;
} eg[];
int n,m,tt,head[],v[],dis[],pre[],s,t;
char map[][];
void init()
{
tt=;
memset(head,-,sizeof(head));
s=;
t=n*m+;
}
void add(int xx,int yy,int cc,int ww)
{
eg[tt].x=xx;
eg[tt].y=yy;
eg[tt].c=cc;
eg[tt].w=ww;
eg[tt].next=head[xx];
head[xx]=tt++;
eg[tt].x=yy;
eg[tt].y=xx;
eg[tt].c=;
eg[tt].w=-ww;
eg[tt].next=head[yy];
head[yy]=tt++;
}
int spfa(int s,int t)
{
queue<int>q;
for(int i=; i<=t; i++)
{
v[i]=;
dis[i]=inf;
pre[i]=-;
}
v[s]=;
dis[s]=;
q.push(s);
while(!q.empty())
{
int ff=q.front();
q.pop();
v[ff]=;
for(int i=head[ff]; i!=-; i=eg[i].next)
{
int w1=eg[i].y;
if(eg[i].c&&dis[w1]>dis[ff]+eg[i].w)
{
dis[w1]=dis[ff]+eg[i].w;
pre[w1]=i;//用边表建图存储其信息
if(!v[w1])
{
v[w1]=;
q.push(w1);
}
}
}
}
if(dis[t]==inf)
{
return ;
}
return ;
}
void KM(int s,int t)
{
int min1,ans=;
while(spfa(s,t)==)
{
min1=inf;
for(int i=pre[t]; i!=-; i=pre[eg[i].x])
{
if(min1>=eg[i].c)
{
min1=eg[i].c;
}
}
for(int i=pre[t]; i!=-; i=pre[eg[i].x])
{
eg[i].c-=min1;
eg[i+].c+=min1;
}
ans+=min1*dis[t];
}
printf("%d\n",ans);
return ;
}
int main()
{
int t1,t2;
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==&&m==) break;
init();
t1=;
t2=;
for(int i=; i<=n; i++)
{
scanf("%s",map[i]+);//因为要创建超级源点,所以从一比较好计算
for(int j=; j<=m; j++)
{
int l=(i-)*m+j;//以点建图
if(map[i][j]=='m')
{
add(s,l,,);
a[t1].x=i;
a[t1++].y=j;
}
else if(map[i][j]=='H')
{
add(l,t,,);
b[t2].x=i;
b[t2++].y=j;
}
}
}
for(int i=; i<t1; i++)
{
int l1=(a[i].x-)*m+a[i].y;//以点建图
for(int j=; j<t2; j++)
{
int l2=abs(a[i].x-b[j].x)+abs(a[i].y-b[j].y);
int l3=(b[j].x-)*m+b[j].y;//以点建图
add(l1,l3,,l2);
}
}
KM(s,t);
}
return ;
}
POJ2195:Going Home(费用流入门)的更多相关文章
- POJ2195 Going Home[费用流|二分图最大权匹配]
Going Home Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 22088 Accepted: 11155 Desc ...
- 使用Guava RateLimiter限流入门到深入
前言 在开发高并发系统时有三把利器用来保护系统:缓存.降级和限流 缓存: 缓存的目的是提升系统访问速度和增大系统处理容量 降级: 降级是当服务出现问题或者影响到核心流程时,需要暂时屏蔽掉,待高峰或者问 ...
- JavaIo流入门篇之字节流基本使用。
一 基本知识了解( 字节流, 字符流, byte,bit是啥?) /* java中字节流和字符流之前有接触过,但是一直没有深入的学习和了解. 今天带着几个问题,简单的使用字节流的基本操作. 1 什么 ...
- Java-io流入门到精通详细总结
IO流:★★★★★,用于处理设备上数据. 流:可以理解数据的流动,就是一个数据流.IO流最终要以对象来体现,对象都存在IO包中. 流也进行分类: 1:输入流(读)和输出流(写). 2:因为处理的数据不 ...
- IO流入门-第十三章-File相关
/* java.io.File 1.File和流无关,不能通过该类完成文件的读写 2.File是文件和目录路径名的抽象变现形式. */ import java.io.*; public class F ...
- IO流入门-第十二章-ObjectInputStream_ObjectOutputStream
DataInputStream和DataOutputStream基本用法和方法示例,序列化和反序列化 import java.io.Serializable; //该接口是一个“可序列化”的 ,没有任 ...
- IO流入门-第十一章-PrintStream_PrintWriter
DataInputStream和DataOutputStream基本用法和方法示例 /* java.io.PrintStream:标准的输出流,默认打印到控制台,以字节方式 java.io.Print ...
- IO流入门-第十章-DataInputStream_DataOutputStream
DataInputStream和DataOutputStream基本用法和方法示例 /* java.io.DataOutputStream 数据字节输出流,带着类型写入 可以将内存中的“int i = ...
- IO流入门-第九章-BufferedReader_BufferedWriter复制
利用BufferedReader和BufferedWriter进行复制粘贴 import java.io.*; public class BufferedReader_BufferedWriterCo ...
随机推荐
- Java精选笔记_面向对象(多态、异常)
多态 概述 可以理解为事物存在的多种体现形态.同样的引用调用同样的方法却做了不同的事情 多态的本质是:一个程序中同名的不同方法. 多态的体现 父类的引用指向子类的对象,父类的引用接收子类的对象. 多态 ...
- MySQL技术内幕:SQL编程 第2章 数据类型 读书笔记
2.1 类型属性 2.1.1 UNSIGNED 数字无符号化, INT的值 -2147483648 ~ 2147483647 INT UNSIGNED的值 0 ~ 4294967295 int a ...
- 监控之_nrpe
监控机上安装nagios插件和nrpe(nrpe添加为xinetd服务) 1.添加nagios用户 /usr/sbin/useradd nagios passwd nagios 2.安装nagio ...
- 在linux中添加环境变量
首先用命令查看配置了哪些环境变量 env命令查看 编辑环境变量命令 vim ~/.bash_profile Counter_HOME=/home/test/Counterexport Counter ...
- MongoDB启动报错
启动mongodb的时候报错: [root@localhost bin]# ./mongod --dbpath /usr/java/mongoNode/data/db --logpath /usr/j ...
- int()
int() 用于将一个对象转换为整数,可转换的对象如下: In [1]: int(') # 将纯数字的字符串转换为整数 Out[1]: 10 In [2]: int(10.6) # 将浮点数转换为整数 ...
- php和mySQL结合使用
首先,我建立了一个名为class的表,里面有cid,cname,cnum,我想用php代码来实现这一效果,步骤如下: 1.链接数据库 mysqli_set_charset($coon,"ut ...
- 安装postgresql之后为什么找不到postgresql service
没有正常启动 postgresql service.可以 在运行里面 输入 services.msc 找到 postgresql 的服务.启动他.或者也可以用postgres 自带的 工具pg_ctl ...
- LeetCode——Pascal's Triangle II
Description: Given an index k, return the kth row of the Pascal's triangle. For example, given k = 3 ...
- linux如何设置用户权限
linux与用户权限设置: 1.添加用户 首先用adduser命令添加一个普通用户,命令如下: #adduser tommy //添加一个名为tommy的用户 #passwd tommy //修改密码 ...