题意:

给出n个点,以及每个点到其他点的有向距离,要求设计线路使得每一个点都在一个环中,如果设计的线路拥有最小值,那么这个线路就是可选的。输出这个最小值或者说明最小线路不存在。

思路:

在DAG的最小路径覆盖中,找到的最大匹配数实际是非终点的点的最大数量(每一个匹配对应一个起点),点数减去这个数量就是终点的最少数量,一个终点对应一条路径,所以这个路径覆盖是最小的。

这个题要求每一个点都在一个环中,也就是说找到一个设计线路的方案使之不存在DAG,那么自然就没有终点存在,也就意味着每一个点都可以作为起点,即是每一个点都有匹配,那么终点的数量就为0,所以只要这个图存在完美匹配,那么方案就一定存在。

用匈牙利算法找一下最大匹配,若最大匹配数量为n,那么方案就存在,接下来要找的就是最小的权值,既带权二分图的最小匹配,所以修改KM算法即可。

复杂度O(n^3)。

代码:

 #include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
using namespace std; const int N = ;
const int inf = 0x3f3f3f3f; int match[N],mp[N][N];
int link[N];
bool vis[N];
bool vis_x[N],vis_y[N];
int slack[N];
int lx[N],ly[N]; vector<int> g[N]; bool dfs(int u)
{
vis_x[u] = ; for (int j = ;j < g[u].size();j++)
{
int i = g[u][j]; if (vis_y[i]) continue; int gap = lx[u] + ly[i] - mp[u][i]; if (gap == )
{
vis_y[i] = ; if (match[i] == - || dfs(match[i]))
{
match[i] = u; return true;
}
}
else
{
slack[i] = min(gap,slack[i]);
}
} return false;
} int km(int n)
{
memset(match,-,sizeof(match));
memset(ly,,sizeof(ly)); for (int i = ;i <= n;i++)
{
lx[i] = mp[i][]; for (int j = ;j <= n;j++)
{
lx[i] = max(lx[i],mp[i][j]);
}
} for (int i = ;i <= n;i++)
{
memset(slack,inf,sizeof(slack)); while ()
{
memset(vis_x,,sizeof(vis_x));
memset(vis_y,,sizeof(vis_y)); if (dfs(i)) break; int d = inf; for (int j = ;j <= n;j++)
{
if (!vis_y[j]) d = min(d,slack[j]);
} for (int j = ;j <= n;j++)
{
if (vis_x[j]) lx[j] -= d;
if (vis_y[j]) ly[j] += d;
}
}
} int ans = ; for (int i = ;i <= n;i++)
{
ans += mp[match[i]][i];
} return ans;
} bool dfs2(int u)
{
for (int i = ;i < g[u].size();i++)
{
int v = g[u][i]; if (vis[v]) continue; vis[v] = ; if (link[v] == - || dfs2(link[v]))
{
link[v] = u; return true;
}
} return false;
} bool hungary(int n)
{
memset(link,-,sizeof(link));
int res = ;
for (int i = ;i <= n;i++)
{
memset(vis,,sizeof(vis));
if (dfs2(i)) res++;
} return res >= n;
} int main()
{
int n; while (scanf("%d",&n) != EOF && n)
{
for (int i = ;i <= n;i++)
{
for (int j = ;j <= n;j++)
mp[i][j] = -inf;
} for (int i = ;i <= n;i++) g[i].clear(); for (int i = ;i <= n;i++)
{
int a,b; while (scanf("%d",&a) != EOF)
{
if (a == ) break; scanf("%d",&b); mp[i][a] = -b; g[i].push_back(a);
}
} if (hungary(n))
{
printf("%d\n",-km(n));
}
else
{
printf("N\n");
}
} return ;
}

uvalive 3353 Optimal Bus Route Design的更多相关文章

  1. UVaLive 3353 Optimal Bus Route Design (最小费用流)

    题意:给定一个 n 个点的有向带权图,让你找若干个圈,使得每个结点恰好属于一个圈,并且总长度尽量小. 析:一开始想的是先缩点,先用DP,来求... 题解给的是最小费用流或者是最佳完全匹配,其实都是一样 ...

  2. UVa1349 Optimal Bus Route Design(二分图最佳完美匹配)

    UVA - 1349 Optimal Bus Route Design Time Limit: 3000MS Memory Limit: Unknown 64bit IO Format: %lld & ...

  3. UVA1349 Optimal Bus Route Design 拆点法+最小费用最佳匹配

    /** 题目:UVA1349 Optimal Bus Route Design 链接:https://vjudge.net/problem/UVA-1349 题意:lrj入门经典P375 给n个点(n ...

  4. UVA - 1349 D - Optimal Bus Route Design

    4. D - Optimal Bus Route Design 题意:给出n(n<=100)个点的带权有向图,找出若干个有向圈,每个点恰好属于一个有向圈.要求权和尽量小. 注意即使(u,v)和( ...

  5. UVa 1349 (二分图最小权完美匹配) Optimal Bus Route Design

    题意: 给出一个有向带权图,找到若干个圈,使得每个点恰好属于一个圈.而且这些圈所有边的权值之和最小. 分析: 每个点恰好属于一个有向圈 就等价于 每个点都有唯一后继. 所以把每个点i拆成两个点,Xi  ...

  6. UVA 1349 Optimal Bus Route Design 最优公交路线(最小费用流,拆点)

    题意: 给若干景点,每个景点有若干单向边到达其他景点,要求规划一下公交路线,使得每个景点有车可达,并且每个景点只能有1车经过1次,公车必须走环形回到出发点(出发点走2次).问是否存在这样的线路?若存在 ...

  7. UVA1349:Optimal Bus Route Design

    题意:给定一个有向带权图,找若干个环,使得每个点属于且仅属于一个环,要求使得环权值之和最小 题解:发现这题中每个点属于且仅属于一个环,这时候"仅"这种恰好的含义,让我们想到了匹配问 ...

  8. UVa 1349 - Optimal Bus Route Design(二分图最佳完美匹配)

    链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  9. UVa 1349 Optimal Bus Route Design (最佳完美匹配)

    题意:给定一个有向图,让你找出若干个图,使得每个点恰好属于一个圈,并且总的权和最小. 析:每个点都有唯一的一个圈,也就是说每一点都有唯一的后继,那么我们就可以转换成求一个图的最小权的最佳完全匹配,可以 ...

随机推荐

  1. 20165336 2017-2018-2 《Java程序设计》第8周学习总结

    20165336 2017-2018-2 <Java程序设计>第8周学习总结 教材学习内容总结 第十二章 1.程序:一段静态的代码.进程:程序的一次动态执行过程,它对应了从代码加载.执行至 ...

  2. 【python基础】利用pandas处理Excel数据

    参考:https://www.cnblogs.com/liulinghua90/p/9935642.html 一.安装第三方库xlrd和pandas 1:pandas依赖处理Excel的xlrd模块, ...

  3. ubuntu安装jupyter 并设置远程访问

    Jupyter Notebook是一个Web应用程序,允许您创建和共享包含实时代码,方程,可视化和说明文本的文档. 简单的介绍就是:Jupyter Notebook是Ipython的升级版,而Ipyt ...

  4. oracle常见的执行计划

    访问表的执行计划: 全表扫描:TABLE ACCESS FULL ROWID扫描:TABLE ACCESS BY USER ROWID (ROWID来源于用户在where条件中的指定)或 TABLE ...

  5. Innodb buffer 相关参数

    buffer相关参数: show GLOBAL VARIABLES LIKE 'innodb_buffer_pool_instances'; show GLOBAL VARIABLES LIKE 'i ...

  6. svn 启动命令讲解

    svn默认端口是3690 svn启动命令详解 svn启动命令详解 svnserve --help usage: svnserve [-d | -i | -t | -X] [options] Valid ...

  7. jmeter报错:内存溢出

    使用jmeter进行压力测试时,经常会遇到内存溢出错误: 2018-08-28 09:01:26,686 ERROR o.a.j.JMeter: Uncaught exception: java.la ...

  8. Python3学习之路~0 目录

    目录 Python3学习之路~2.1 列表.元组操作 Python3学习之路~2.2 简单的购物车程序 Python3学习之路~2.3 字符串操作 Python3学习之路~2.4 字典操作 Pytho ...

  9. Node.js学习看这里:基础、进阶、文章

    Node.js是基于Chrome JavaScript运行时建立的一个平台,实际上它是对Google Chrome V8引擎进行了封装,它主要用于创建快速的.可扩展的网络应用. Node.js采用事件 ...

  10. python tkinter Treeview 事件绑定

    def trefun(event): sels= event.widget.selection()#event.widget获取Treeview对象,调用selection获取选择对象名称 for i ...