专题十 匹配问题 POJ 2594 Treasure Exploration -----DAG最小相交路径覆盖(DAG二分图最大匹配+floyd传递闭包)

POJ 2594 Treasure Exploration

题意:

在一个DAG(有向无环图)里,求最小路径数点覆盖。(线路可以相交)

反思

最 小 路 径 覆 盖 数 = n − m a x m a t c h 最小路径覆盖数=n-maxmatch =nmaxmatch

  1. 相关证明1:传送门
  2. 相关证明2:传送门

思路1:

  1. 先跑一遍floyd传递闭包
  2. 之后跑最大匹配

AC1

#include 
#include 
#include 
#include 
#define mst(x,a) memset(x,a,sizeof(x))
using namespace std;
const int maxn=500+10;
const int maxm=5000+10;
int vis[maxn];
bool used[maxn],link[maxn][maxn];
int n,m;
void floyd(){
    for(int k=1; k<=n; k++){
        for(int i=1; i<=n; i++){
            for(int j=1; j<=n; j++){
                if(link[i][k]&&link[k][j])link[i][j]=true;
            }
        }
    }
}
bool dfs(int u){
    //for(int i=head[u]; i!=-1; i=e[i].next){
    for(int v=1; v<=n; v++){
        if(link[u][v]&&!used[v]){
            used[v]=1;
            if(!vis[v]||dfs(vis[v])){
                vis[v]=u;
                return 1;
            }
        }
    }
    return 0;
}
void sol(){
    int ans=0;
    for(int i=1; i<=n; i++){
        mst(used,0);
       // if(!vis[i])
       ans+=dfs(i);
    }
    printf("%d\n",n-ans);
}
void init(){
    int u,v;
    mst(link,0);mst(vis,0);
    for(int i=1; i<=m; i++)scanf("%d%d", &u, &v),link[u][v]=true;//,add(u,v);
}
int main()
{
    while(scanf("%d%d", &n, &m)&&(n||m)){
        init();
        floyd();
        sol();
    }
    return 0;
}

思路2:

  1. 先跑一遍floyd传递闭包
  2. 跑了闭包后,问题就转换成了不相交最小路径覆盖
  3. 之后跑最大流。

你可能感兴趣的:(#,最短路,#,匹配问题)