给出一个n*m的图,其中m是人,H是房子,.是空地,满足人的个数等于房子数。

现在让每个人都选择一个房子住,每个人只能住一间,每一间只能住一个人。

每个人可以向4个方向移动,每移动一步需要1$,问所有人移动到房子里的最少花费。

其中,n,m<=100,最多有100个人。

最小给用流裸题。

建立一个超级源点,跟每一个房子连一条边,容量为1,花费为0

每一个人与超级汇点连一条边,容量为1,花费为0

一个房子与每一个人建一条边,房子指向人,容量为1,花费用2者的距离(不是直线距离)

然后跑最小费用流算法就可以了。

 #include<cstdio>
#include<cstring>
#include<vector>
#include<queue> using namespace std; const int maxn=;
const int inf=0x3f3f3f3f;
const int s=;
int t;
int tot;
char maze[maxn];
char str[maxn][maxn];
bool vis[maxn];
int dis[maxn];
int prev[maxn];
int pree[maxn]; struct Point
{
int x,y;
};
Point point[maxn];
struct Edge
{
int to,cap,cost,rev;
};
vector<Edge>edge[maxn]; inline int get_abs(int tmp)
{
if(tmp>)
return tmp;
return -tmp;
} inline int min(int x,int y)
{
return x<y?x:y;
} inline int get_dis(int i,int j)
{
return get_abs(point[i].x-point[j].x)+get_abs(point[i].y-point[j].y);
} void addedge(int from,int to,int cap,int cost)
{
edge[from].push_back((Edge){to,cap,cost,edge[to].size()});
edge[to].push_back((Edge){from,,-cost,edge[from].size()-});
} void build_graph(int n,int m)
{
//要从0开始
for(int i=;i<maxn;i++)
edge[i].clear();
tot=;
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)
{
if(str[i][j]=='H')
{
point[tot].x=i;
point[tot++].y=j;
}
}
}
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)
{
if(str[i][j]=='m')
{
point[tot].x=i;
point[tot++].y=j;
}
}
}
t=tot;
tot--;
tot/=;
for(int i=;i<=tot;i++)
{
addedge(s,i,,);
addedge(i+tot,t,,);
}
for(int i=;i<=tot;i++)
{
for(int j=tot+;j<=tot*;j++)
{
addedge(i,j,,get_dis(i,j));
}
}
} void spfa()
{
memset(vis,false,sizeof vis);
for(int i=;i<=t;i++)
dis[i]=inf;
queue<int>que;
while(!que.empty())
que.pop();
que.push(s);
dis[s]=;
vis[s]=true;
while(!que.empty())
{
int u=que.front();
que.pop();
vis[u]=false; //要记得这步
for(int i=;i<edge[u].size();i++)
{
Edge &e=edge[u][i];
if(e.cap>&&dis[e.to]>dis[u]+e.cost)
{
dis[e.to]=dis[u]+e.cost;
prev[e.to]=u;
pree[e.to]=i;
if(!vis[e.to])
{
vis[e.to]=true;
que.push(e.to);
}
}
}
}
return ;
} int solve()
{
int ret=;
int flow=tot;
while(flow>)
{
spfa();
int f=flow;
for(int i=t;i!=s;i=prev[i])
{
f=min(f,edge[prev[i]][pree[i]].cap);
}
flow-=f;
ret+=dis[t]*f;
for(int i=t;i!=s;i=prev[i])
{
Edge &e=edge[prev[i]][pree[i]];
e.cap-=f;
edge[e.to][e.rev].cap+=f;
}
}
return ret;
} int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
if(!n&&!m)
break;
for(int i=;i<=n;i++)
{
scanf("%s",str[i]+);
}
build_graph(n,m);
printf("%d\n",solve());
}
return ;
}

POJ 2195 Going Home 最小费用流 裸题的更多相关文章

  1. POJ 3068 运送危险化学品 最小费用流 模板题

    "Shortest" pair of paths Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 1215 ...

  2. poj 1201 Intervals——差分约束裸题

    题目:http://poj.org/problem?id=1201 差分约束裸套路:前缀和 本题可以不把源点向每个点连一条0的边,可以直接把0点作为源点.这样会快许多! 可能是因为 i-1 向 i 都 ...

  3. POJ 2195 Going Home 最小费用流

    POJ2195 裸的最小费用流,当然也可以用KM算法解决,但是比较难写. 注意反向边的距离为正向边的相反数(因此要用SPFA) #include<iostream> #include< ...

  4. POJ 1469 ZOJ1140 二分匹配裸题

    很裸,左点阵n,右点阵m 问最大匹配是否为n #include <cstdio> #include <cstring> #include <vector> usin ...

  5. POJ 2195 Going Home 最小费用流 难度:1

    Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 17955   Accepted: 9145 Descr ...

  6. poj 2407 欧拉函数裸题

    http://poj.org/problem?id=2407 题意:多组数据,每次输入一个数 ,求这个数的欧拉函数 int euler_phi(int n){//单个欧拉函数 int m=(int)s ...

  7. POJ 3461 Oulipo(KMP裸题)

    Description The French author Georges Perec (1936–1982) once wrote a book, La disparition, without t ...

  8. POJ 1287 Networking(最小生成树裸题有重边)

    Description You are assigned to design network connections between certain points in a wide area. Yo ...

  9. 主席树----POJ 2104(主席树裸题)(转)

    首先来介绍一下我们需求:给你n个数,多次问你某个区间内的第k小是哪个数 主席树: 主席树的全名应该是 函数式版本的线段树.加上附带的一堆 technology.. ..总之由于原名字太长了,而且 “主 ...

随机推荐

  1. HDU 5234 Happy birthday --- 三维01背包

    HDU 5234 题目大意:给定n,m,k,以及n*m(n行m列)个数,k为背包容量,从(1,1)开始只能往下走或往右走,求到达(m,n)时能获得的最大价值 解题思路:dp[i][j][k]表示在位置 ...

  2. URAL 1208 Legendary Teams Contest(DFS)

    Legendary Teams Contest Time limit: 1.0 secondMemory limit: 64 MB Nothing makes as old as years. A l ...

  3. php MySQL数据库操作类源代码

    php MySQL数据库操作类源代码: <?php class MySQL{ private $host; //服务器地址 private $name; //登录账号 private $pwd; ...

  4. K650D安装黑苹果

    1.需要UEFI+GPT模式的win8或win10 2.关闭UEFI模式,进PE,分一个400M的分区,格式化为FAT16或EFI模式 3.制作clover模式的MAC安装U盘:链接: http:// ...

  5. 小巧灵便高效的spx6.0截图三件套(带注册码)

    非常好用截图工具,推荐截图必备,这是三件套完整版本. SPX Instant Screen Capture 是一小巧的屏幕抓图工具,可以抓取选定的区域或整个窗口,可以将抓取的图片发送到剪贴板或 ema ...

  6. freeswitch 接通后再录音

    需求 录音时不要将前置媒体录制进去. 用法 <action application="set" data="media_bug_answer_req=true&qu ...

  7. ADS1110/ADS1271

    ADS1110 1.初始化 软件:设置p任意2个为GPIO口 硬件:设置p0.2,p0.3为SDA,SCL 输入.输出 ADS1110的I2C地址(1001aaa)例如ADS1110A0的地址是100 ...

  8. JSBinding + SharpKit / 安装SharpKit以及添加SharpKit工程

    本文说明如何往 sln 中添加 SharpKit 工程,以及配置. SharpKit 工程用于将 C# 源代码编译成 JS  代码. QQ群 189738580 1. 安装SharpKit 到 sha ...

  9. JavaScript-闭包注意事项

    闭包允许内层函数引用父函数中的变量,但是该变量是最终值

  10. C#中有关string和byte[]转换的问题

    byte[] byteArray = System.Text.Encoding.Default.GetBytes( str ); 怎么样,够简单吧? 反过来也是一样,把byte[]转成string: ...