poj3020 Antenna Placement 二分匹配之最小路径覆盖
2011-02-09 09:02
281 查看
题目的意思大致就是,一个矩形中,有N个城市,现在这n个城市都要覆盖无线,若放置一个基站,那么它至多可以覆盖相邻的两个城市。
问至少放置多少个基站才能使得所有的城市都覆盖无线?
构图:行扫描所有城市,编号,如果有城市相邻就连一条边,当然如果3和4相邻,首先graph[3][4]=1,当扫描到4时graph[4][3]也连一条边,最后只需要取一半即可.求最大匹配的一半,这样可以得到所有2个相邻城市被一个基站覆盖所需要的基站数。然后再加上独立的那些基站即可。
公式是:N-最大匹配(代表所有可以和相邻城市配对的城市数)+最大匹配/2=N-最大匹配/2;
SourceCode
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
intnx,ny;//X的點數目、Y的點數目
intmx[405],my[405];//X各點的配對對象、Y各點的配對對象
boolvy[405];//紀錄GraphTraversal拜訪過的點
booladj[405][405];//精簡過的adjacencymatrix
intxx,n,m,cc[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
charg[41][11];
//以DFS建立一棵交錯樹
boolDFS(intx)
{
for(inty=0;y<ny;++y)
if(adj[x][y]&&!vy[y])
{
vy[y]=true;
//找到擴充路徑
if(my[y]==-1||DFS(my[y]))
{
mx[x]=y;my[y]=x;
returntrue;
}
}
returnfalse;
}
intbipartite_matching()
{
//全部的點初始化為未匹配點。
memset(mx,-1,sizeof(mx));
memset(my,-1,sizeof(my));
//依序把X中的每一個點作為擴充路徑的端點,
//並嘗試尋找擴充路徑。
intc=0;
for(intx=0;x<nx;++x)
//if(mx[x]==-1)//x為未匹配點,這行可精簡。
{
//開始GraphTraversal
memset(vy,false,sizeof(vy));
if(DFS(x))c++;
}
returnc;
}
voidini()
{
inta,b;
xx=0;
for(inti=0;i<n;i++)
for(intj=0;j<m;j++)
{
if(g[i][j]=='*')
{
xx++;
a=i*m+j;
for(inth=0;h<4;h++)
{
if(i+cc[h][0]>=0&&i+cc[h][0]<n&&j+cc[h][1]>=0&&j+cc[h][1]<m&&g[i+cc[h][0]][j+cc[h][1]]=='*')
{
b=(i+cc[h][0])*m+j+cc[h][1];
adj[a][b]=1;
}
}
}
}
nx=ny=m*n;
}
main()
{
intt,i;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
memset(adj,0,sizeof(adj));
getchar();
for(i=0;i<n;i++)
gets(g[i]);
ini();
printf("%d\n",xx-bipartite_matching()/2);
}
system("pause");
}
问至少放置多少个基站才能使得所有的城市都覆盖无线?
构图:行扫描所有城市,编号,如果有城市相邻就连一条边,当然如果3和4相邻,首先graph[3][4]=1,当扫描到4时graph[4][3]也连一条边,最后只需要取一半即可.求最大匹配的一半,这样可以得到所有2个相邻城市被一个基站覆盖所需要的基站数。然后再加上独立的那些基站即可。
公式是:N-最大匹配(代表所有可以和相邻城市配对的城市数)+最大匹配/2=N-最大匹配/2;
SourceCode
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
intnx,ny;//X的點數目、Y的點數目
intmx[405],my[405];//X各點的配對對象、Y各點的配對對象
boolvy[405];//紀錄GraphTraversal拜訪過的點
booladj[405][405];//精簡過的adjacencymatrix
intxx,n,m,cc[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
charg[41][11];
//以DFS建立一棵交錯樹
boolDFS(intx)
{
for(inty=0;y<ny;++y)
if(adj[x][y]&&!vy[y])
{
vy[y]=true;
//找到擴充路徑
if(my[y]==-1||DFS(my[y]))
{
mx[x]=y;my[y]=x;
returntrue;
}
}
returnfalse;
}
intbipartite_matching()
{
//全部的點初始化為未匹配點。
memset(mx,-1,sizeof(mx));
memset(my,-1,sizeof(my));
//依序把X中的每一個點作為擴充路徑的端點,
//並嘗試尋找擴充路徑。
intc=0;
for(intx=0;x<nx;++x)
//if(mx[x]==-1)//x為未匹配點,這行可精簡。
{
//開始GraphTraversal
memset(vy,false,sizeof(vy));
if(DFS(x))c++;
}
returnc;
}
voidini()
{
inta,b;
xx=0;
for(inti=0;i<n;i++)
for(intj=0;j<m;j++)
{
if(g[i][j]=='*')
{
xx++;
a=i*m+j;
for(inth=0;h<4;h++)
{
if(i+cc[h][0]>=0&&i+cc[h][0]<n&&j+cc[h][1]>=0&&j+cc[h][1]<m&&g[i+cc[h][0]][j+cc[h][1]]=='*')
{
b=(i+cc[h][0])*m+j+cc[h][1];
adj[a][b]=1;
}
}
}
}
nx=ny=m*n;
}
main()
{
intt,i;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
memset(adj,0,sizeof(adj));
getchar();
for(i=0;i<n;i++)
gets(g[i]);
ini();
printf("%d\n",xx-bipartite_matching()/2);
}
system("pause");
}
相关文章推荐
- poj3020 Antenna Placement 二分匹配 最小路径覆盖
- 【POJ3020】【总数-最大二分匹配】【最小路径覆盖和点覆盖的区别是 路径的话要所有点覆盖了】
- Poj 1548 Robots【最小路径覆盖---二分匹配】
- [HIHO1394]最小路径覆盖(二分匹配,最小路径覆盖)
- HDU 1151Air Raid 最小路径覆盖=n-最大匹配量 (第二道二分匹配)
- HDU 1151Air Raid 最小路径覆盖=n-最大匹配量 (第二道二分匹配)
- poj3020_最小覆盖路径(顶点个数-二分图最大匹配数)
- POJ 1422 二分匹配 最小路径覆盖(邻接表实现)
- HDU 1151Air Raid 最小路径覆盖=n-最大匹配量 (第二道二分匹配)
- POJ1325二分匹配或者DINIC(最小路径覆盖)
- HDU3861 (强连通缩点+二分匹配最小路径覆盖)
- POJ-3020-Antenna Placement [二分匹配][最小路径覆盖]
- poj 2594 Treasure Exploration(可重点最小路径覆盖)(二分匹配+Floyd求传递闭包)
- poj3216 Repairing Company 二分匹配之最小路径覆盖+最短路
- poj2594 Treasure Exploration 二分匹配之最小路径覆盖+传递闭包
- POJ 2594 最大二分匹配 最小路径覆盖
- hdu1151(二分匹配最小路径覆盖)
- poj3020 匈牙利算法+公式:二分无向图的最小路径覆盖 = 顶点数 - 最大二分匹配数 / 2
- POJ 3020 最小路径覆盖 = 顶点数-最大匹配数 二分匹配
- 【二分匹配】 [网络流24题] 最小路径覆盖问题