题意
给出n*n矩阵,有k个障碍,每次可以消灭一行或一列障碍,问至少需要消灭多少次。
思路
障碍点的行和列连边。
普通写法
#include <algorithm> //STL通用算法
#include <bitset> //STL位集容器
#include <cmath>
#include <cstdio>
#include <cstring>
#include <deque> //STL双端队列容器
#include <exception> //异常处理类
#include <fstream>
#include <functional> //STL定义运算函数(代替运算符)
#include <limits>
#include <list> //STL线性列表容器
#include <map> //STL 映射容器
#include <iomanip>
#include <ios> //基本输入/输出支持
#include<iosfwd> //输入/输出系统使用的前置声明
#include <iostream>
#include <istream> //基本输入流
#include <ostream> //基本输出流
#include <queue> //STL队列容器
#include <set> //STL 集合容器
#include <sstream> //基于字符串的流
#include <stack> //STL堆栈容器
#include <string> //字符串类
#include <vector> //STL动态数组容器
#define ll long long
using namespace std;
#define ll long long
#define maxn 500+66
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define dep(i,a,b) for(int i=a;i>=b;i--)
#define mod 1000000007
#define INF 0x3f3f3f3f
int un,uv;///0开始
int linker[maxn];
int g[maxn][maxn];
bool used[maxn];
bool dfs(int u)
{
rep(v,0,uv-1)
{
if(g[u][v]&&!used[v])
{
used[v]=true;
if(linker[v]==-1||dfs(linker[v]))
{
linker[v]=u;
return true;
}
}
}
return false;
}
int solve()
{
int ans=0;
memset(linker,-1,sizeof(linker));
rep(u,0,un-1)
{
memset(used,0,sizeof(used));
if(dfs(u))
ans++;
}
return ans;
}
int main()
{
int n,k;
while(~scanf("%d%d",&n,&k))
{
memset(g,0,sizeof(g));
un=uv=n;
while(k--)
{
int x,y;
scanf("%d%d",&x,&y);
g[x-1][y-1]=1;
}
int ans=solve();
printf("%d\n",ans);
}
return 0;
}
优化版HK
#include <algorithm> //STL通用算法
#include <bitset> //STL位集容器
#include <cmath>
#include <cstdio>
#include <cstring>
#include <deque> //STL双端队列容器
#include <exception> //异常处理类
#include <fstream>
#include <functional> //STL定义运算函数(代替运算符)
#include <limits>
#include <list> //STL线性列表容器
#include <map> //STL 映射容器
#include <iomanip>
#include <ios> //基本输入/输出支持
#include<iosfwd> //输入/输出系统使用的前置声明
#include <iostream>
#include <istream> //基本输入流
#include <ostream> //基本输出流
#include <queue> //STL队列容器
#include <set> //STL 集合容器
#include <sstream> //基于字符串的流
#include <stack> //STL堆栈容器
#include <string> //字符串类
#include <vector> //STL动态数组容器
#define ll long long
using namespace std;
#define ll long long
#define maxn 500+66
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define dep(i,a,b) for(int i=a;i>=b;i--)
#define mod 1000000007
#define INF 0x3f3f3f3f
struct node
{
int to;
int nxt;
} e[maxn*maxn];
struct Two
{
int head[maxn*2];
int color[maxn];
int dep[maxn];
int dx[maxn];
int dy[maxn];
int mx[maxn];
int my[maxn];
int n,m,cnt;
void init(int nn,int mm)
{
cnt=0;
n=nn;
m=mm;
///cout<<n<<" "<<m<<endl;
rep(i,0,maxn*2-1)head[i]=-1;
}
void add_edge(int u,int v)
{
e[cnt].to=v;
e[cnt].nxt=head[u];
head[u]=cnt++;
}
int bfs()
{
int flag=0;
queue<int>q;
for(int i=0; i<=n+1; i++)
{
dx[i]=-1;
}
for(int i=0; i<=m+1; i++)
{
dy[i]=-1;
}
for(int i=0; i<n; i++)
if(mx[i]==-1)
q.push(i);
while(!q.empty())
{
int u=q.front();
//cout<<u<<endl;
q.pop();
for(int k=head[u]; k!=-1; k=e[k].nxt)
{
int v=e[k].to;
if(dy[v]==-1)
{
dy[v]=dx[u]+1;
if(my[v]==-1)
flag=1;
else
{
dx[my[v]]=dy[v]+1;
q.push(my[v]);
}
}
}
}
return flag;
}
bool dfs(int u)
{
//cout<<u<<endl;
for(int k=head[u]; k!=-1; k=e[k].nxt)
{
int v=e[k].to;
if(dy[v]==dx[u]+1)
{
dy[v]=-1;
if(my[v]==-1||dfs(my[v]))
{
my[v]=u;
mx[u]=v;
return 1;
}
}
}
return 0;
}
int solve()
{
for(int i=0; i<=n+1; i++)
{
mx[i]=-1;
}
for(int i=0; i<=m+1; i++)
{
my[i]=-1;
}
int ans = 0;
while(bfs())
{
//cout<<"11"<<endl;
for(int i = 0; i < n; ++i)
if(mx[i] == -1 && dfs(i))
ans++;
}
return ans;
}
} D;
int vis[maxn][maxn];
int id[maxn][maxn];
int main()
{
int n,k;
while(scanf("%d %d",&n,&k)!=EOF)
{
memset(vis,0,sizeof(vis));
D.init(n,n);
rep(i,1,k)
{
int x,y;
scanf("%d %d",&x,&y);
vis[x][y]=1;
D.add_edge(x-1,y-1);
}
int ans=D.solve();
printf("%d\n",ans);
}
}