您的位置:首页 > 其它

POJ 1422 二分匹配 最小路径覆盖(邻接表实现)

2016-07-22 11:02 330 查看
题意:一个地图上有n个小镇,以及连接着其中两个小镇的有向边,而且这些边无法形成回路。现在选择一些小镇空降士兵(1个小镇最多1个士兵),士兵能沿着边走到尽头,问最少空降几个士兵,能遍历完所有的小镇。

思路:匈牙利算法求最小路径覆盖:在一个有向图中,路径覆盖就是在图中找一些路径,使之覆盖了图中的所有顶点,且任何一个顶点有且只有一条路径与之关联;(如果把这些路径中的每条路径从它的起始点走到它的终点,那么恰好可以经过图中的每个顶点一次且仅一次);解决此类问题可以建立一个二分图模型。把所有顶点i拆成两个:X结点集中的i和Y结点集中的i’,如果有边i->j,则在二分图中引入边i->j’,设二分图最大匹配为m,则结果就是n-m

#include<cstring>
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
#define LL long long
#define INF 0x3f3f3f3f
const int MAXN=1505;//这个值要超过两边个数的较大者,因为有linker
int linker[MAXN];
bool used[MAXN];
vector<int>mp[MAXN];
int uN;
bool dfs(int u)
{
for(int i=0;i<mp[u].size();i++)
{
if(!used[mp[u][i]])
{
used[mp[u][i]]=true;
if(linker[mp[u][i]]==-1||dfs(linker[mp[u][i]]))
{
linker[mp[u][i]]=u;
return true;
}
}
}
return false;
}
int hungary()
{
int u;
int res=0;
memset(linker,-1,sizeof(linker));
for(u=1;u<=uN;u++)
{
memset(used,false,sizeof(used));
if(dfs(u)) res++;
}
return res;
}

int u,v;
int T,k;
int main(){
scanf("%d",&T);
while(T--){
scanf("%d%d",&uN,&k);
for(int i=1;i<=uN;i++)mp[i].clear();
while(k--){
scanf("%d%d",&u,&v);
mp[u].push_back(v);
}
printf("%d\n",uN-hungary());
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: