poj1422-最小路径覆盖(不交叉)&二分图-Air Raid

https://vjudge.net/problem/POJ-1422
给定一个图。点代表小城镇,边代表小城镇的路,你可以再一个点投一个伞兵,那个sb可以出发,经过任何他所经过的点,问你最少投多少伞兵。
要求①:伞兵不可以交叉。
思路① dfs?但是是有向图,不是求连通分量那种。
② topsort也是不行的,因为只能求topsort并不能确定有分叉的情况。
③ 正解,二分图求 最小路径覆盖。

#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
/* 
*/
const int maxn=200;
int mp[maxn][maxn];
int linker[maxn];
bool used[maxn];
int m,n;
bool dfs(int u){
      for(int v=1;v<=m;v++){
          if(mp[u][v]&&!used[v]){
              used[v]=true;
              if(linker[v]==-1||dfs(linker[v])){
                 linker[v]=u;
                 return true;
              }
          }
      }
      return false;
}
int t;
int main()
{   int a,b;
    scanf("%d",&t);
    while(t--){
    memset(mp,0,sizeof(mp));
    scanf("%d%d",&m,&n);
      for(int i=0;i<n;i++){
          scanf("%d%d",&a,&b);
          mp[a][b]=1;
      }
     /* for(int k=1;k<=m;k++){
          for(int i=1;i<=m;i++){
             for(int j=1;j<=m;j++)
                if(mp[i][k]&&mp[k][j])
                mp[i][j]=1;
          }
      }*/
      int res=0;
      memset(linker,-1,sizeof(linker));
      for(int i=1;i<=m;i++){
          memset(used,0,sizeof(used));
          if(dfs(i)){
            res++;
            }
      }
     // cout<<res<<endl;
      printf("%d\n",m-res);//最小路径覆盖就是顶点数-匹配数
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值