游戏高手的烦恼
时间限制:1000 ms | 内存限制:65535 KB
难度:5
- 描写叙述
-
有一位传说级游戏高手。在闲暇时间里玩起了一个小游戏,游戏中,一个n*n的方块形区域里有很多敌人。玩家能够使用炸弹炸掉某一行或者某一列的全部敌人。
他是种玩什么游戏都想玩得非常优秀的人。所以。他决定。使用尽可能少的炸弹炸掉全部的敌人。
如今给你一个游戏的状态,请你帮助他推断最少须要多少个炸弹才干炸掉全部的敌人吧。
比方说,下图中X表示敌人
X . X
. X .
. X .
则,他仅仅须要炸掉第1行与第2列就能炸掉全部的敌人,所以仅仅须要两颗炸弹就能够了。
题意就是用最少的炸弹 消灭全部敌人 也就是最小点覆盖。
而最小点覆盖能够通过最大匹配实现。
要想求最大匹配 最好的算法就是匈牙利算法
而在这道题中 怎样构图又成了不easy理解的地方。我们能够这样想
因为炸弹能够炸一行或一列
假设第i行 第j列有一个敌人 能够想象成 i点和j点有关系。
问题就变成点击打开链接
#include <stdio.h>
#include <vector>
#include <string.h>
using namespace std;
vector<int>map[505];
bool vis[505];
int conn[505];
bool dfs(int x)
{
for(int i=0;i<map[x].size();i++)
{
int y=map[x][i];
if(!vis[y])
{
vis[y]=true;
if(conn[y]==0||dfs(conn[y]))
{
conn[y]=x;
return true;
}
}
}
return false;
}
int main()
{
int ncase;
scanf("%d",&ncase);
while(ncase--)
{
int n,k;
memset(conn,0,sizeof(conn));
memset(map,0,sizeof(map));
scanf("%d %d",&n,&k);
for(int i=0;i<k;i++)
{
int a,b;
scanf("%d %d",&a,&b);
map[a].push_back(b);
}
int ans=0;
for(int i=1;i<=n;i++)
{
memset(vis,false,sizeof(vis));
if(dfs(i))
ans++;
}
printf("%d
",ans);
}
return 0;
}