hdu 4862 KM算法 最小K路径覆盖的模型

http://acm.hdu.edu.cn/showproblem.php?pid=4862

选t<=k次,t条路要经过所有的点一次并且仅仅一次,

建图是问题:

我自己最初就把n*m 个点分别放入X集合以及Y集合,再求最优匹配,然后连样例都过不了,而且其实当时解释不了什么情况下不能得到结果,因为k此这个条件相当于没用上。。。

建图方法:

1、X集合和Y集合都放入n*m+k个点,X中前n*m个点和Y中前n*m个点之间,如果格子里的值相等,权就是(收益-耗费),不等就是(-耗费),因为要的是最大收益,所以初始时,所有点之间权值为-1;

原因:如下图,1->2  2->3  3->1   二分图的边本身不和其他边相连,但是这样的建图方式,使得可以找到连同路径1->2->3

由此学到的一种思维方式:二分图又称作二部图,是图论中的一种特殊模型。 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图。但是如果两个子集是一样的,那么就能通过二分图的算法找路径或者连通分量

  

这样建图需要避免的是1->1,这种自环的情况,导致有些点不能被覆盖,避免的方法就是初始化的时候,因为要的是最大收益,所以把自环的边初始化为最小值,

2、X中后k个点到Y中前n*m个点,权值为0。Y中后k个点到X中前n*m个点,权值也为0。加入的k个点是作为起点和终点,起点到第一个格子不需要耗费

3、X中k个点和Y中k个点一一对应的权值为0  因为允许少于k次把图遍历完成,k个点中,有自环,说明这次不需要用

建图说的应该够清了,以后复习也好用

帖代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>

using namespace std;

#define rep(i,s,e) for(int i=s;i<e;i++)

const int INF = 999999;//
const int MAXN = 11*11+150;
int n,matv[MAXN][MAXN],mat[MAXN][MAXN],match[MAXN];
bool sx[MAXN],sy[MAXN];
int lx[MAXN],ly[MAXN];
char line[MAXN];

inline int ABS(int x)
{
    return x>=0?x:-x;
}

bool path(int u)
{
    sx[u]=true;
    rep(v,0,n)
        if(!sy[v] && lx[u]+ly[v]==mat[u][v])
        {
            sy[v]=1;
            if(match[v]==-1 || path(match[v]))
            {
                match[v]=u;
                return true;
            }
        }
    return false;
}

int KM()
{
    rep(i,0,n)
    {
        lx[i]=-INF;
        ly[i]=0;
        rep(j,0,n)
        {
            lx[i]=max(lx[i],mat[i][j]);
        }
    }
    memset(match, 0xff, sizeof(match));
    rep(u,0,n)
    {
        while(1)
        {
            memset(sx,0,sizeof(sx));
            memset(sy,0,sizeof(sy));
            if(path(u))break;
            int dmin=INF;
            rep(i,0,n)
                if(sx[i])
                    rep(j,0,n)
                        if(!sy[j])
                            dmin=min(lx[i]+ly[j]-mat[i][j],dmin);
            rep(i,0,n)
            {
                if(sx[i])
                    lx[i]-=dmin;
                if(sy[i])
                    ly[i]+=dmin;
            }
        }
    }
    int sum=0;
    rep(j,0,n)////
    {
        if(mat[match[j]][j] == -INF)return -INF;
        sum+=mat[match[j]][j];
    }
    return sum;
}

void init(int nn, int mm,int kk)
{
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        {
            mat[i][j]=-INF;
        }
    rep(i,nn*mm,n)
        mat[i][i]=0;
    rep(i,0,nn)
        rep(j,0,mm)
        {
            rep(ii,0,kk)
                mat[nn*mm+ii][i*mm+j]=mat[i*mm+j][nn*mm+ii]=0;
            //right
                rep(jj,j+1,mm)
                {
                    if(matv[i][j] == matv[i][jj])
                    {
                        mat[i*mm+j][i*mm+jj]=matv[i][j]-ABS(j-jj)+1;
                    }
                    else
                    {
                        mat[i*mm+j][i*mm+jj]=-ABS(j-jj)+1;
                    }
                }
            //below
                rep(ii,i+1,nn)
                {
                    if(matv[i][j] == matv[ii][j])
                    {
                        mat[i*mm+j][ii*mm+j]=matv[i][j]-ABS(i-ii)+1;//变量写错。。。
                    }
                    else
                    {
                        mat[i*mm+j][ii*mm+j]=-ABS(i-ii)+1;
                    }
                }
        }
}

int main()
{
    //freopen("hdu4862.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int ncase;
    int nn,kk,mm;
    scanf("%d",&ncase);
    for(int icase=1;icase<=ncase;icase++)
    {
        scanf("%d%d%d",&nn,&mm,&kk);
        n=nn*mm+kk;
        rep(i,0,nn)
        {
            scanf("%s",line);
            rep(j,0,mm)
            {
                matv[i][j]=line[j]-'0';
            }
        }
        init(nn,mm,kk);
        int ans=KM();
        if(ans<=-INF)printf("Case %d : -1\n",icase);
        else printf("Case %d : %d\n", icase, ans);
    }
    return 0;
}

hdu 4862 KM算法 最小K路径覆盖的模型,布布扣,bubuko.com

时间: 2024-10-07 07:36:16

hdu 4862 KM算法 最小K路径覆盖的模型的相关文章

HDU 4862 Jump(最小K路径覆盖)

输入一个n×m网格图,每个结点的值为0-9,可以从任意点出发不超过k次,走完每个点且仅访问每个结点一次,问最终的能量最大值.不可全部走完的情况输出-1. 初始能量为0. 而结点(x,y)可以跳跃到结点(x,y+dy)或(x+dx,y).消耗能量为跳跃前后结点的曼哈顿距离 - 1 .若跳跃前后的结点的值相等,能量加上那个值. 具体建图可以参考这里http://blog.sina.com.cn/s/blog_6bddecdc0102uy9g.html 最小K路径覆盖其实在之前是见过的打过的,不过这次

HDU 4862 Jump (最小K路径覆盖)

HDU 4862 Jump 链接:http://acm.hdu.edu.cn/showproblem.php?pid=4862 题意:给定一个N*M的矩阵,矩阵里面为0~9的数字.现在规定从一个点可以跳到它正下方和正右方的点,花费的费用为曼哈顿距离 - 1.如果在跳的过程中,两个点的数字相同,那么将得到该点的数字.规定可以从任意点开始跳,每个点只能经过1次.最多可以选择K个点来作为起点进行跳跃.问能否经过所有的点,如果可以,那么花费的费用是多少. 思路: 如果是最小路径覆盖,那么很容易构造图.但

HDU 4862 Jump(最大k路径覆盖 费用流)(待续)

题意:一个n*m的矩阵,需要遍历所有点,从起点出发每次只可向右或向下跳,若到达位置的数字与上一步的数字相同,则获得该数字大小的能量: 否则消耗能量:哈密顿距离减1:求可获得的最大能量: 思路:网络流之最大k路径覆盖. 源点向n*m各点建流量为1,费用为0的边: n*m各点向汇点建流量为1,费用为0的边: 新增一个起点: 源点向起点建流量为k,费用为0的边:起点向各点建流量1,费用为0的边: n*m各点间建边: 建好图后跑最小费用最大流,如果满流则存在解,否则不存在:最小费用的相反数就是所能够获得

HDU 4862 Jump 最小k路径覆盖 费用流

gg... 题意: 给定n*m的矩阵 选<=k个起点 每个起点可以向右或向下跳任意步 花费是2点间的曼哈顿距离 若2个格子的数字一样 则赚取格子上的数字的价值 问:遍历整个图的最小花费 若不能遍历则输出-1 #include <stdio.h> #include <string.h> #include <iostream> #include <math.h> #include <queue> #include <set> #in

HDU 4862 Jump (2014-多校1-1002,最小K路径覆盖,最小费用最大流)

题目: http://acm.hdu.edu.cn/showproblem.php?pid=4862 题意: 给你一个n*m的矩阵,填充着0-9的数字,每次能从一个点出发,到它的右边或者下边的点,花费为|x1-x2|+|y1-y2|-1,如果跳跃的起点和终点的数字相同,则获得这个数字的收益,不能走已经走过的点 有K次重新选择起点的机会 如果可以走遍所有点,则输出最大的价值(收益-花费) 否则,输出-1 方法: 最小K路径覆盖,最小费用最大流 建图: 每个点拆为2点:X部和Y部,(a,b)表示流量

hdu 3488(KM算法||最小费用最大流)

Tour Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total Submission(s): 2925    Accepted Submission(s): 1407 Problem Description In the kingdom of Henryy, there are N (2 <= N <= 200) cities, with M (M <= 30000

有向无环图的最小路径覆盖 二分图模型解题

有向无环图中,路径覆盖就是在图中找一些路径,使之覆盖了图中的所有顶点,且任何一个顶点有且只有一条路径与之关联(如果把这些路径中的每条路径从它的起始点走到它的终点,那么恰好可以经过图中的每个顶点一次且仅一次). 最小路径覆盖就是找出最小的路径条数,使之成为原图的一个路径覆盖. 公式:最小路径覆盖=(原图)顶点数-对应的二分图的最大匹配数. 我们通过例题来解释如何把DAG转换为二分图模型. HDU1151Air Raid 题目大意:在一个城镇,有n个路口,和m条单向路,而且这些路不会形成环.现在要弄

Antenna Placement(匈牙利算法 ,最少路径覆盖)

Antenna Placement Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6991   Accepted: 3466 Description The Global Aerial Research Centre has been allotted the task of building the fifth generation of mobile phone nets in Sweden. The most st

hdu 2448(KM算法+SPFA)

Mining Station on the Sea Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2997    Accepted Submission(s): 913 Problem Description The ocean is a treasure house of resources and the development o