您的位置:首页 > 其它

匈牙利算法讲解与习题练习

2017-09-13 18:43 197 查看
讲解:点击这里

超详细的入门

A - 过山车 HDU - 2063

RPG girls今天和大家一起去游乐场玩,终于可以坐上梦寐以求的过山车了。可是,过山车的每一排只有两个座位,而且还有条不成文的规矩,就是每个女生必须找个个男生做partner和她同坐。但是,每个女孩都有各自的想法,举个例子把,Rabbit只愿意和XHD或PQK做partner,Grass只愿意和linle或LL做partner,PrincessSnow愿意和水域浪子或伪酷儿做partner。考虑到经费问题,boss刘决定只让找到partner的人去坐过山车,其他的人,嘿嘿,就站在下面看着吧。聪明的Acmer,你可以帮忙算算最多有多少对组合可以坐上过山车吗?

Input

输入数据的第一行是三个整数K , M , N,分别表示可能的组合数目,女生的人数,男生的人数。0

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=2000;
struct node
{
int v,next;
}edge[maxn*2+100];
int head[maxn],inpath[maxn],match[maxn];
int cnt=0,m,n;
void init()
{
cnt=0;
memset(head,-1,sizeof(head));
memset(inpath,0,sizeof(inpath));
memset(match,-1,sizeof(match));
}
void add_edge(int u,int v)
{
edge[cnt].v=v;
edge[cnt].next=head[u];
head[u]=cnt++;
}
int xiongyali(int s)
{
int i;
for(i=head[s];i!=-1;i=edge[i].next)
{
int to=edge[i].v;
if(!inpath[to])
{
inpath[to]=1;
if(match[to]==-1||xiongyali(match[to]))
{
match[to]=s;
return 1;
}
}
}
return 0;
}
void zzz()
{
int i;
int ans=0;
for(i=1;i<=m;i++)
{
memset(inpath,0,sizeof(inpath));
if(xiongyali(i))
{
ans++;
}
}
printf("%d\n",ans);
}
int main ()
{
int k;
while(~scanf("%d",&k))
{
if(k==0)
break;
init();
scanf("%d%d",&m,&n);
while(k--)
{
int xx,yy;
scanf("%d%d",&xx,&yy);
add_edge(xx,yy);
}
zzz();
}
}


B - Asteroids POJ - 3041

Bessie wants to navigate her spaceship through a dangerous asteroid field in the shape of an N x N grid (1 <= N <= 500). The grid contains K asteroids (1 <= K <= 10,000), which are conveniently located at the lattice points of the grid.

Fortunately, Bessie has a powerful weapon that can vaporize all the asteroids in any given row or column of the grid with a single shot.This weapon is quite expensive, so she wishes to use it sparingly.Given the location of all the asteroids in the field, find the minimum number of shots Bessie needs to fire to eliminate all of the asteroids.

Input

* Line 1: Two integers N and K, separated by a single space.

* Lines 2..K+1: Each line contains two space-separated integers R and C (1 <= R, C <= N) denoting the row and column coordinates of an asteroid, respectively.

Output

*
f23f
Line 1: The integer representing the minimum number of times Bessie must shoot.

Sample Input

3 4

1 1

1 3

2 2

3 2

Sample Output

2

Hint

INPUT DETAILS:

The following diagram represents the data, where “X” is an asteroid and “.” is empty space:

X.X

.X.

.X.

OUTPUT DETAILS:

Bessie may fire across row 1 to destroy the asteroids at (1,1) and (1,3), and then she may fire down column 2 to destroy the asteroids at (2,2) and (3,2).

翻译:

Bessie 驾驶着他的太空飞船呆呆2号在太空旅行,途径一段危险地带,他希望自己能安全通过这段区域,于是他将这片区域的地图扫描进入了太空飞船,地图是一个N x N的网络 (1 <= N <= 500),其中有K颗小行星 (1 <= K <= 10,000)。

还好Bessie有一个强力的武器能够一发光束将一整行或者一整列的小行星轰成灰烬。 这种光束的价格高昂,材料稀有,所以他希望更少的使用这个光束。现在把地图给你,你能帮Bessie计算一下,摧毁掉这些小行星至少需要几发光束。

Input

* Line 1: 两个整数N和K,中间用空格隔开。

* Lines 2..K+1: 每一行有两个整数R和C (1 <= R, C <= N) ,代表行和列,即小行星i的位置是(Ri,Ci)。

Output

* Line 1: 输出一个整数表示最少需要几发光束。

也算是模板题,相当于行列的匹配

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=10000+100;
int head[maxn],inpath[maxn],match[maxn],have[maxn];
struct node
{
int v,next;
}edge[maxn+100];
int cnt,n,k;
void init()
{
cnt=0;
memset(head,-1,sizeof(head));
memset(inpath,0,sizeof(inpath));
memset(match,-1,sizeof(match));
}
void add_edge(int u,int v)
{
edge[cnt].v=v;
edge[cnt].next=head[u];
head[u]=cnt++;
}
int xiongyali(int s)
{
int i;
for(i=head[s];i!=-1;i=edge[i].next)
{
int to=edge[i].v;
if(!inpath[to])
{
inpath[to]=1;
if(match[to]==-1||xiongyali(match[to]))
{
match[to]=s;
return 1;
}
}
}
return 0;
}
void zzz()
{
int i;
int ans=0;
for(i=1;i<=n;i++)
{
memset(inpath,0,sizeof(inpath));
if(have[i]&&xiongyali(i))
{
ans++;
}
}
printf("%d\n",ans);
}
int main ()
{
scanf("%d%d",&n,&k);
init();
while(k--)
{
int xx,yy;
scanf("%d%d",&xx,&yy);
have[xx]=1;
add_edge(xx,yy);
}
zzz();
}


C - Antenna Placement POJ - 3020

The Global Aerial Research Centre has been allotted the task of building the fifth generation of mobile phone nets in Sweden. The most striking reason why they got the job, is their discovery of a new, highly noise resistant, antenna. It is called 4DAir, and comes in four types. Each type can only transmit and receive signals in a direction aligned with a (slightly skewed) latitudinal and longitudinal grid, because of the interacting electromagnetic field of the earth. The four types correspond to antennas operating in the directions north, west, south, and east, respectively. Below is an example picture of places of interest, depicted by twelve small rings, and nine 4DAir antennas depicted by ellipses covering them.

Obviously, it is desirable to use as few antennas as possible, but still provide coverage for each place of interest. We model the problem as follows: Let A be a rectangular matrix describing the surface of Sweden, where an entry of A either is a point of interest, which must be covered by at least one antenna, or empty space. Antennas can only be positioned at an entry in A. When an antenna is placed at row r and column c, this entry is considered covered, but also one of the neighbouring entries (c+1,r),(c,r+1),(c-1,r), or (c,r-1), is covered depending on the type chosen for this particular antenna. What is the least number of antennas for which there exists a placement in A such that all points of interest are covered?

Input

On the first row of input is a single positive integer n, specifying the number of scenarios that follow. Each scenario begins with a row containing two positive integers h and w, with 1 <= h <= 40 and 0 < w <= 10. Thereafter is a matrix presented, describing the points of interest in Sweden in the form of h lines, each containing w characters from the set [‘‘,’o’]. A ‘‘-character symbolises a point of interest, whereas a ‘o’-character represents open space.

Output

For each scenario, output the minimum number of antennas necessary to cover all ‘*’-entries in the scenario’s matrix, on a row of its own.

Sample Input

2

7 9

ooo**oooo

*oo*ooo

o*oo**o**

ooooooooo

*******oo

o*o*oo*oo

*******oo

10 1

*

*

*

o

*

*

*

*

*

*

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=2000;
int cnt=0;
int h,w;
char mapp[maxn][maxn];
int used[maxn][maxn];
int mmp[maxn][maxn];
int head[maxn],inpath[maxn],match[maxn];
int dir[4][2]={-1,0,0,1,1,0,0,-1};
struct node
{
int v,next;
}edge[maxn*3];
int n=0;
void add_edge(int u,int v)
{
edge[cnt].v=v;
edge[cnt].next=head[u];
head[u]=cnt++;
}
int sum=0;
void init()
{
memset(mmp,0,sizeof(mmp));
memset(head,-1,sizeof(head));
memset(inpath,0,sizeof(inpath));
memset(match,-1,sizeof(match));
cnt=0;
sum=0;
n=0;
}
int xiongliya(int s)
{
int i;
for(i=head[s];i!=-1;i=edge[i].next)
{
int to=edge[i].v;
if(!inpath[to])
{
inpath[to]=1;
if(match[to]==-1||xiongliya(match[to]))
{
match[to]=s;
return 1;
}
}
}
return 0;
}
void zzz()
{
int i,ans=0;
for(i=1;i<=n;i++)
{
memset(inpath,0,sizeof(inpath));
if(xiongliya(i))
{
ans++;
}
}
printf("%d\n",sum-ans/2);
}
int main ()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&h,&w);
int i,j;
init();
for(i=1;i<=h;i++)
{
for(j=1;j<=w;j++)
scanf(" %c",&mapp[i][j]);
}
for(i=1;i<=h;i++)
{
for(j=1;j<=w;j++)
{
if(mapp[i][j]=='*')
{
mmp[i][j]=++n;
}
else
{
mmp[i][j]=0;
}
}
}
int aaa;
for(i=1;i<=h;i++)
{
for(j=1;j<=w;j++)
{
if(mmp[i][j]>0)
{
sum++;
for(aaa=0;aaa<4;aaa++)
{
int tx,ty;
tx=i+dir[aaa][0];
ty=j+dir[aaa][1];
if(mmp[tx][ty]&&tx>=1&&ty>=1&&tx<=h&&ty<=w)
{
add_edge(mmp[i][j],mmp[tx][ty]);
}
}
}
}
}
zzz();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: