POJ2594Treasure Exploration(非简单路径覆盖)

来源:互联网 发布:农村淘宝网官网 编辑:程序博客网 时间:2024/05/18 01:25

对于有向图,求简单路径(即不相交路径)覆盖,可以通过转化成二分图通过求最大匹配来得到。

那么对于非简单路径(即相交路径)覆盖,要先通过floyd求传递闭包,将间接相连的点也连起来,然后求最大匹配。

代码:

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define N 505
#define INF (1<<30)
bool G[N][N],vis[N];
int Mx[N],My[N],dx[N],dy[N],dis,Nx,Ny;
bool bfs(){
    queue<int> q;dis=INF;int u;
    memset(dx,-1,sizeof(dx));
    memset(dy,-1,sizeof(dy));
    for(int i=1;i<=Nx;++i){
        if(Mx[i]==-1){dx[i]=0;q.push(i);}
    }
    while(!q.empty()){
        u=q.front();q.pop();
        if(dx[u]>dis) break;
        for(int i=1;i<=Ny;++i){
            if(G[u][i]&&dy[i]==-1){
                dy[i]=dx[u]+1;
                if(My[i]==-1) dis=dy[i];
                else{
                    dx[My[i]]=dy[i]+1;q.push(My[i]);
                }
            }
        }
    }
    return dis!=INF;
}
bool dfs(int u){
    for(int i=1;i<=Ny;++i){
        if(G[u][i]&&!vis[i]&&dy[i]==dx[u]+1){
            vis[i]=true;
            if(My[i]!=-1&&dy[i]==dis) continue;
            if(My[i]==-1||dfs(My[i])){
                My[i]=u;Mx[u]=i;return true;
            }
        }
    }
    return false;
}
int MaxMatch(){
    int ans=0;
    memset(Mx,-1,sizeof(Mx));
    memset(My,-1,sizeof(My));
    while(bfs()){
        memset(vis,false,sizeof(vis));
        for(int i=1;i<=Nx;++i){
            if(Mx[i]==-1&&dfs(i)) ++ans;
        }
    }
    return ans;
}
void floyd(int n){
    for(int i=1;i<=n;++i){
        for(int j=1;j<=n;++j){
            if(G[i][j]) continue;
            for(int k=1;k<=n;++k){
                if(G[i][k]&&G[k][j]){G[i][j]=true;break;}
            }
        }
    }
}
int main(){
    int n,m,a,b;
    while(scanf("%d%d",&n,&m)&&!(n==0&&m==0)){
        Nx=Ny=n;memset(G,0,sizeof(G));
        for(int i=0;i<m;++i){
            scanf("%d%d",&a,&b);
            G[a][b]=true;
        }
        floyd(n);
        printf("%d\n",n-MaxMatch());
    }
    return 0;
}

0 0