POJ 2594 Treasure Exploration

Floyd传递闭包+DAG的最小路径覆盖

先来一次Floyd传递闭包,然后再求最大匹配,n-最大匹配就是答案

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
using namespace std;

const int MAXN=550;

int linker[MAXN];
bool used[MAXN];
vector<int>Map[MAXN];
int uN;
int jz[MAXN][MAXN];
int n,m;

bool dfs(int u)
{
    for(int i=0; i<Map[u].size(); i++)
    {
        if(!used[Map[u][i]])
        {
            used[Map[u][i]]=true;
            if(linker[Map[u][i]]==-1||dfs(linker[Map[u][i]]))
            {
                linker[Map[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;
}

void floyd()
{
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(jz[i][k]&&jz[k][j])
                    jz[i][j]=1;
}

int main()
{
    int u,k,v;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(jz,0,sizeof jz);
        if(n==0&&m==0) break;
        for(int i=0; i<=n; i++) Map[i].clear();
        for(int i=0; i<m; i++)
        {
            scanf("%d%d",&u,&v);
            jz[u][v]=1;
        }
        floyd();
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(jz[i][j])
                    Map[i].push_back(j);
        uN=n;
        printf("%d\n",n-hungary());
    }
    return 0;
}
时间: 2024-08-10 03:19:33

POJ 2594 Treasure Exploration的相关文章

POJ 2594 Treasure Exploration(最小路径覆盖变形)

POJ 2594 Treasure Exploration 题目链接 题意:有向无环图,求最少多少条路径能够覆盖整个图,点能够反复走 思路:和普通的最小路径覆盖不同的是,点能够反复走,那么事实上仅仅要在多一步.利用floyd求出传递闭包.然后依据这个新的图去做最小路径覆盖就可以 代码: #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using names

poj 2594 Treasure Exploration (二分匹配)

Treasure Exploration Time Limit: 6000MS   Memory Limit: 65536K Total Submissions: 6558   Accepted: 2644 Description Have you ever read any book about treasure exploration? Have you ever see any film about treasure exploration? Have you ever explored

Poj 2594 Treasure Exploration (最小边覆盖+传递闭包)

题目链接: Poj 2594 Treasure Exploration 题目描述: 在外星上有n个点需要机器人去探险,有m条单向路径.问至少需要几个机器人才能遍历完所有的点,一个点可以被多个机器人经过. 解题思路: 一眼看上去是普通的最小边覆盖,但是仔细想后发现如果在原图上进行最大匹配的话,每个点只能经过一次.这样的话对于本题求出的并不是最优解,所以我们要先对原图进行传递闭包处理,然后再进行最大匹配. 这个题目点数太少H_K和匈牙利算法在空间和时间上并没有什么差,就代码复杂度而言匈牙利算法更有优

POJ 2594 —— Treasure Exploration——————【最小路径覆盖、可重点、floyd传递闭包】

Treasure Exploration Time Limit:6000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 2594 Description Have you ever read any book about treasure exploration? Have you ever see any film about treasure exploratio

poj 2594 Treasure Exploration 最少边覆盖+传递闭包

给出一个有向无环图,问最少多少条边就可以覆盖所有的点,很明显的最少路径覆盖问题,但是点可以重复用,这与hungary算法不太一样,我们可以这样处理,假设a要经过b点到c,但是b点已经被访问过,为了保证a顺利到c,就让a直接飞过b到c,也就是说添加一条a到c的边,这其实就是求传递闭包,我们可以通过floyd算法求出.然后ans=n-hungary(). 一开始用了邻接表的最大二分匹配,在求闭包的时候用的dfs,但是超时了,估计是求闭包的时候加边过多导致的,而且还要判断边是否重复,因此在时空复杂度允

poj 2594 Treasure Exploration 二分图匹配

点击打开链接题目链接 Treasure Exploration Time Limit: 6000MS   Memory Limit: 65536K Total Submissions: 7215   Accepted: 2947 Description Have you ever read any book about treasure exploration? Have you ever see any film about treasure exploration? Have you eve

poj 2594 Treasure Exploration(最小路径覆盖/二分最大匹配)

Treasure Exploration Time Limit: 6000MS   Memory Limit: 65536K Total Submissions: 7208   Accepted: 2944 Description Have you ever read any book about treasure exploration? Have you ever see any film about treasure exploration? Have you ever explored

POJ 2594 Treasure Exploration 最小可相交路径覆盖

最小路径覆盖 DAG的最小可相交路径覆盖: 算法:先用floyd求出原图的传递闭包,即如果a到b有路径,那么就加边a->b.然后就转化成了最小不相交路径覆盖问题. 这里解释一下floyd的作用如果1->2->3->4那么1可以到达2,3,4只要需要借助一些点,那么就可以直接把1与2,3,4相连,这就是floyd要做的事. 证明:为了连通两个点,某条路径可能经过其它路径的中间点.比如1->3->4,2->4->5.但是如果两个点a和b是连通的,只不过中间需要经

POJ 2594 Treasure Exploration【传递闭包+最小路径覆盖】

大意: 有n个点,告诉你一些单向边,问多少条边能把所有的点覆盖[注意点能重复覆盖  比如4->1->2   5->3] 分析: 知识储备: 传递闭包:  所谓传递,可以这么理解,对于节点j如果i能到k并且k能到j那么i能到j,这样用像floyed就能处理出任意两个点能否到达 for(int k = 1; k <= n; k++) { for(int i = 1; i <= n; i++) { if(W[i][k]) { for(int j = 1; j <= n; j+