网络流专题总结

 ACM Computer Factory

 POJ - 3436 

题意:

第一行输入P N 代表零件数和机器数

接下来N行 有2*N+1个数,第一个数代表单位时间可以操作的数量,P个数代表输入这个机器的格式,P个数代表输入这个机器的格式(输入:1表示必须有,2无所谓,0代表必须没有;  输出:0表示改部件没有,1表示有)

求可以生产的最大数量,并且输出那些机器之间必须有边。

解:

建立源点s,汇点t

s和输入和输入格式都为0的机器连边(容量为inf);

输出格式都为1的机器和连边(容量为inf);

机器之间:机器a的输出和机器b的输入格式一样,建立a到b的边(容量为inf);

每台机器进行拆点,机器a1和机器a2连边(容量为几区单位时间可以操作的数量)

然后跑最大流可以求出所能生产的最大数量;

遍历一下两两机器之间的边,如果残余图和开始的图的流量减少了,则这两个机器之间一定有边

 

 Dining

 POJ - 3281

有N头牛,F种食物,D种饮料,

第一行给出N,F,D;

下面N行,先给出Fi,Di代表这头牛喜欢的食物和饮料的个数,然后Fi个数,代表喜欢的食物是哪几个,Di个数,代表喜欢的饮料是哪几个;

让你求出最大数量的牛可以吃到自己喜欢的食物和饮料。

解:

建立源点s,汇点t

s和每个食物相连,(容量为1(每个食物只能提供给一头牛))

每种饮料喝t、相连,(容量为1(每种饮料只能提供给一头牛))

每头牛拆点,牛a1--->牛a2(容量为1(每头牛只能吃一种食物和一种饮料))

跑最大流即可。

 

A Plug for UNIX

 POJ - 1087

题意:首先给你一个n,代表有n种插座,下面n行给你插座的种类。

  再给你一个m代表用电器的数量,下面m行,给出每个用电器需要的插的插座是哪个(每个用电器只有一个专一的插座可以使用)

接着给你一个f,是转换器的数量,接下来f行,给你两个插座的型号u,v;表明插座u可以转换为v

(每种插座的数量只有一个,但是每种转换器的数量是无限的)

问你,可以使用的用电器的数量的最大值

解:

建立源点s,汇点t

s和每个现在有的n种插座相连(容量为1)

m种用电器和t相连(容量为1)

每个相匹配的用插座和用电器相连(容量为1)

每个可以相互转换的插座之间相连(容量为inf);

建好图之后跑最大流即可

 

 

 Going Home

 POJ - 2195       (最小费用流

输入样例:

5 5
HH..m
.....
.....
.....
mm..H
7 8
...H....
...H....
...H....
mmmHmmmm
...H....
...H....
...H....

题意:

给你一个n行m列的图,m代表那里有一个小人,H代表那里有一个房子;

人可以上下左右的走动,走动一格的花费是1

让你求,所有的人回家所花费的最小代价;

建立源点s和汇点t

将源点和所有的人相连(容量为1,花费为0)

将所有的房子和汇点相连(容量为1,花费为0)

将所有的房子和人两两相连(容量为1,花费为他们之间的距离)

建好图之后跑最小费用最大流即可

 

 

Minimum Cost

 POJ - 2516    (最小费用流

题意:

有N个店主(标记从1到N)存货。经销商有M个供应点(标记从1到M),每个供应点提供K种不同的货物(标记从1到K)。一旦店主订购货物,经销商应安排哪个供应地点向店主提供多少货物,以降低运输总成本。

每个测试用例的第一行包含三个整数n,m,k(0<n,m,k<50)。接下来的N行给出店主的订单,每行包含K个整数(这些整数属于[0,3]),表示每个店主需要的商品数量。接下来的M行给出供应地点的存储,每行包含K个整数(这些整数也属于[0,3]),表示在该供应地点存储的货物数量。

然后是K个整数矩阵(每个都具有N*M的大小),第i行的整数(这个整数属于(0,100)。第k个矩阵中的第j列表示从第j个供应点向第i个店主运输第k个商品单位的成本。

解:

把K种物品分开看,一个一个物品来算,看每个物品供货商是否都能提供给商店

对于每个物品:

{

建立源点s和汇点t;

t和n个商店相连(容量为商店的需求量,费用为0)

m个供货商和s相连(容量为商店的供货量,费用为0)

n个商店和m个供货商两两相连(容量为inf,费用为第K个商品供货商运到商店的费用)

}

以上的图一共建K次,跑K次最小费用最大流,如果每一次都能满足商店的需求量,就输出K次的最小费用的总和,否则输出-1;

 

Power Network

 POJ - 1459 

样例输入:

2 1 1 2 (0,1)20 (1,0)10 (0)15 (1)20
7 2 3 13 (0,0)1 (0,1)2 (0,2)5 (1,0)1 (1,2)8 (2,3)1 (2,4)7
         (3,5)2 (3,6)5 (4,2)7 (4,3)5 (4,5)1 (6,0)5
         (0)5 (1)2 (3)2 (4)1 (5)4

题意:

多组测试数据,每组测试数据给出N,Np,Nc,M。     

N代表结点数, M代表边的数量,Np代表结点中电站的数量(只产电,不耗电),Nc代表消费者数量(只耗电,不产电),其他结点代表中转站(不产电,不耗电)。 
接着M组(u,v)w数据,代表u到v容量为w,接着Np组(u)w,代表结点u产电w,接着Nc组(u)w,代表结点u耗电w。 
求电网中能消耗的最大电能值。

TIP:这道题的输入格式应该是这样的

scanf("%s",ss);

sscanf(ss,"(%d,%d)%d",&x,&y,&z);

或:

scanf("%s",ss);

sscanf(ss,"(%d)%d",&x,&z);

解:

建立源点s和汇点t

s和Np个电站相连(容量为电站的产电量)

Nc个耗电点和t相连(容量为耗电点的耗电量)

M条边u,v相连(容量为w)

建好图后跑最大流即可

 

 

Island Transport

 HDU - 4280 

有N个岛屿和M条航线;

给出N个岛屿的坐标,最西边的那个岛屿是起点,最东边的那个岛屿是终点;

给出M条航线的单位时间可以运送的游客数量;

让你求单位时间从起点到终点可以运送的游客数量

TIP:

这是这个无向图,无向图网络流建图时,正反的流量都赋值就好,有向图的时候正向为流量,反向为0

解:

源点就是最西边的那个点,汇点就是最东边的那个点(容量都为inf)

M条边(u,v)w正反建边(容量为w)

建好图后跑最大流即可

 

 Food

 HDU - 4292 

输入样例:

4 3 3
1 1 1
1 1 1
YYN
NYY
YNY
YNY
YNY
YYN
YYN
NNY

题意:

有N个人,F种食品,D种饮料,接下来一行表示F种食品的数量,再下一行D种饮料的数量,接下来的N行F列表示N个人对F种食品的可以接受情况:Y为可接受,N为不可接受。再接下来N行D列表示N个人对D种饮料可以接受的情况,Y与N和上面的代表相同。问最多能满足多少人,一人任意一种可接受的一个食品和一杯饮料。


解题:源点s与每种食品建边,边权为当前食品的数量;

每种饮料与汇点相连,边权为饮料的数量;

N 个人点拆成一条有向边(两点先命名为左点与右点),边权为1 。每个人: 左点与能接受的食品种类点相连,边权为1;右点与能接受的饮料品种点相连,边权为1。

最后跑一次最大流,最大流值就是最多能满足的人数。

(和上面的第二题的思路差不多)

 

 Control

 HDU - 4289    (最小割、拆点)

给一个无向图,有些不法分子要从vs点vt点,现在要抓住所有的不法分子阻止他们去vt,那么就要控制某一些城市等待他们,控制每个城市花费不同,问最少花费是多少。

解:

源点就是vs,汇点就是vt

相连的城市之间相连(容量为inf)

每个城市进行拆点(容量为这个控制这个城市的花费)

最后跑一遍最大流即可(最小割即为最大流)

 

 

Sabotage

 UVA - 10480

给你N个城市和M条边,割断一条边有一定的花费

问你把城市1和城市2分割开需要的最小花费,输出要割断的城市;

解:

城市1是源点,城市2位汇点,M条边建无向图(权值为w)

怎么输出要割断的城市呢?

在求出最大流之后,残余网络会分成两个部分,残余网中还有流量的是和源点相连的集合点,没有流量的是和汇点相连的集合

那么这两个集合中的点相互连的边就一定要割断啦

for(int i=1;i<=m;i++) //遍历m条边

{

if((le[a[i]]&&!le[b[i]])||(!le[a[i]]&&le[b[i]])) //一个点再汇点集合,另一个是源点集合

      printf("%d %d\n",b[i],a[i]);

}

 

 

Leapin' Lizards

 HDU - 2732 

输入样例:

3 2
00000
01110
00000
.....
.LLL.
.....
5 2
00000000
02000000
00321100
02000000
00000000
........
........
..LLLL..
........
........

在一个迷宫里面有一些蜥蜴,这个迷宫有一些柱子组成的,并且这些柱子都有一个耐久值,每当一只蜥蜴跳过耐久值就会减一,当耐久值为0的时候这个柱子就不能使用了,每个蜥蜴都有一个最大跳跃值d,现在想知道有多少蜥蜴不能离开迷宫(跳出迷宫就可以离开了。)

首先给你一个n和d(最大的跳跃距离)

接下来给你一个n行的矩阵,这个矩阵的值是这个柱子的耐久值,接下来还是一个n行的矩阵,‘L’代表这个柱子是上有一个蜥蜴。

 

解:

建立源点s和汇点t

源点s和有蜥蜴的柱子相连(容量为1)

可以一步跳出去的柱子和汇点t相连(容量为inf)

柱子和柱子之间可以跳跃的两两相连(容量为inf)

柱子自己之间拆点相连(容量为这个柱子的耐力值)

建好图之后跑最大流,用蜥蜴的总数剪去最大流即可

 

 Escape

 HDU - 3605 (二分图多重匹配)

每个数据的开始是n(1<=n<=100000),m(1<=m<=10)n表示地球上有n个人,m代表m行星。、

 

接下来n行,每行有m个数字,第i个数字是1,表示一个人适合生活在第i个行星上,0代表这个人不适合生活在第i个行星上。

最后一行有M个数字,第i个数字AI表示第i个行星可以包含AI人最多。

解:

二分图多重匹配板子敲一下就好,匈牙利算法就可以过

 

 

Marriage Match II

 HDU - 3081

有n个男生n个女生,现在要求将所有的男女配对,所有的男女都配对的话,算该轮游戏结束了。接着另一轮游戏开始,还是男女配对,但是配对的男女不能是之前配对过的。 
问这游戏能玩多少轮 
男女能配对的条件如下 
1.男女未曾吵架过。 
2.如果两个女的是朋友,那么另一个女的男朋友可以和该女的配对

解:

先按题意建图,然后跑最大二分图匹配,如果配对数==n,则把本次配对的边给删除,接着匹配,看能配对多少次,就是答案。

删边的代码:

for(int i=1; i<=n; i++)

      e[match[i]][i]=0;

 

Marriage Match IV

 HDU - 3416

有n个城市m条边,告诉起点和终点,问从起点到终点不走重复边的最短路有多少条。

解:

先从头跑一遍spfa,得到起点到其他所有点的最短路径dis1

再从尾跑一遍spfa,得到终点到其他所有点的最短路径dis2

对于点u,v来说,如果:dis1【u】+dis2【v】+e【i】.w==dis1【t】

for(int i=0;i<m;i++) //遍历m条边

{

if(dis1[b[i].v]+dis2[b[i].u]+b[i].w==dis1[t])

 add2(b[i].v,b[i].u,1);

 }

那么这个边就是最短路上的边;

得出所有最短路上的边之后,建图每条边的容量为1,跑最大流即可

 

 

 

 Kakuro Extension

 HDU - 3338 

题面图片:

       

 

输入样例:

6 6
XXXXXXX XXXXXXX 028\XXX 017\XXX 028\XXX XXXXXXX
XXXXXXX 022\022 ....... ....... ....... 010\XXX
XXX\034 ....... ....... ....... ....... .......
XXX\014 ....... ....... 016\013 ....... .......
XXX\022 ....... ....... ....... ....... XXXXXXX
XXXXXXX XXX\016 ....... ....... XXXXXXX XXXXXXX
5 8
XXXXXXX 001\XXX 020\XXX 027\XXX 021\XXX 028\XXX 014\XXX 024\XXX
XXX\035 ....... ....... ....... ....... ....... ....... .......
XXXXXXX 007\034 ....... ....... ....... ....... ....... .......
XXX\043 ....... ....... ....... ....... ....... ....... .......
XXX\030 ....... ....... ....... ....... ....... ....... XXXXXXX

 

大概题意就是给你一个n*m的矩阵,白格子里面的数,行和应该等于该行黑格子里面的数右边的数,列和应该等于该列左边的数;

解:

这道题真的是建图建到懵逼啊(哇哇哇哇哇)

最大流的性质,流入容量会等于流出容量。和题目中的行总和会等于列总和性质相同,由此可以建图。

为了方便建图,本应填入1~9,改为填入0~8,行列和相应减去,便可同普通的最大流。

建图的时候保存一下第i行j列的tot值,不然到后面很难找。

{

add((i-1)*m+j,(i-1)*m+z,8); //建图后存一下tot

ans[i][z]=tot-2;//减2是因为正反存边

}

建立源点s和汇点t

s和所有的行和相连(容量为行和减去相应的白格子的数)

行和和其对应的白格子相连(容量为8)

白格子和其对应的列和相连(容量为8)

所有的列和跟汇点相连(容量为列和减去相应的白格子数)

跑最大流即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值