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

来源:互联网 发布:淘宝限时特价 编辑:程序博客网 时间:2024/06/06 03:53

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;}