Karp 21个规约问题 笔记 (1~13个规约问题)

0  证明格式

0.1 证明一个问题属于NP

0.2 多项式时间内将一个问题归约到另一个 

0.3 证明一个问题是NP完全的

0.4 要证明的规约

 1 SAT —> 0-1 整数规范

1.1 问题描述

 1.2 规约

 1.3 等价性证明

 2 SAT->CLIQUE

2.1 SAT->3SAT->independent set->clique

MAS 714 笔记20:规约和SAT_UQI-LIUWJ的博客-CSDN博客

MAS 714笔记: NP完全问题_UQI-LIUWJ的博客-CSDN博客

2.2 规约过程

 想象成3SAT->independent set 构造的图的补图

2.3 证明等价性

 3 clique -> Set packing

 3.1 clique->independent set->set packing

MAS 714 笔记20:规约和SAT_UQI-LIUWJ的博客-CSDN博客

MAS 714笔记: NP完全问题_UQI-LIUWJ的博客-CSDN博客

        每个集合对应一个点。如果两个集合有交集,那么这两个集合对应的点在图上有连边。找k个independent set等价于k个互不相交的集合

3.2 规约

3.3 等价性证明 

 4 Clique ->vertex cover(node cover)

4.1 clique->independent set->vertex cover

MAS 714 笔记20:规约和SAT_UQI-LIUWJ的博客-CSDN博客

MAS 714笔记: NP完全问题_UQI-LIUWJ的博客-CSDN博客

4.2 规约过程

这里一步到位,clique->independent set是图变成补图,点不变;independent set 到 node cover是点变成补的点,图不变

4.3 证明等价性

5 node cover->set cover

MAS 714笔记: NP完全问题_UQI-LIUWJ的博客-CSDN博客 4.3

6 node cover ->feedback node  set

6.1 问题描述

 6.2 规约过程

 将一条无向边转化成两个方向的有向边

6.3 等价性证明

 7 node cover->feedback  arc set

7.1 问题描述

7.2 规约过程

大致思路和6差不多,唯一不同的是,6中要求的是,我没构造出来的一个有向环,对应的是一个点。而这里要求的是对应一条有向边,那么怎么对应呢?我们就构建一个如下的内容:

 

 7.3 证明等价性

 8 node-cover—>directed Hamilton circuit

这个比较繁琐,略过,可以用3SAT->independent set->node-cover->->Hamiliton

MAS 714笔记: NP完全问题_UQI-LIUWJ的博客-CSDN博客

MAS 714总复习_UQI-LIUWJ的博客-CSDN博客

 

 

 9 有向哈密顿图-> 无向哈密顿图

9.1 规约方法

 

 9.2 等价性证明

 

 10 SAT->3SAT

MAS 714 笔记20:规约和SAT_UQI-LIUWJ的博客-CSDN博客

11 3SAT->Chromatic number

11.1 问题描述

后者即k-染色问题,相邻的两个点不能染同一种颜色。

11.2 规约过程

 以为例:

 

 11.3 等价性证明

11.3.1 3SAT->

 11.3.2 ->3SAT

 12 chromatic number -> clique cover

12.1 问题描述

12.2 规约问题 

 12.3 证明等价性

 13 chromatic number -> exact cover

13.1 问题描述

 13.2 问题规约

 13.3 证明等价性

13.3.1 ->

 13.3.2 <-

 

后续的可见

 0Reducibility among Combinatorial Problems问题之间的规约证明 - 百度文库 (baidu.com)

  • 4
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,以下是使用Edmonds-Karp算法解决该问题的C++代码: ```c++ #include <iostream> #include <queue> #include <cstring> using namespace std; const int MAXN = 105; // 池塘数量的最大值 const int INF = 0x3f3f3f3f; // 无穷大 int n, m; // n为水渠数量,m为池塘数量 int cap[MAXN][MAXN]; // cap[i][j]表示从池塘i到池塘j的水渠容量 int flow[MAXN][MAXN]; // flow[i][j]表示从池塘i到池塘j的水渠流量 int pre[MAXN]; // pre[i]表示在增广路中,池塘i的前一个池塘编号 int maxflow; // 最大流量 // 使用BFS寻找增广路 bool bfs(int s, int t) { queue<int> q; q.push(s); memset(pre, -1, sizeof(pre)); pre[s] = 0; while (!q.empty()) { int u = q.front(); q.pop(); for (int v = 1; v <= m; v++) { if (pre[v] == -1 && cap[u][v] > flow[u][v]) { pre[v] = u; if (v == t) return true; q.push(v); } } } return false; } // 计算增广路上的最小剩余容量 int getMinFlow(int s, int t) { int minflow = INF; for (int v = t; v != s; v = pre[v]) { int u = pre[v]; minflow = min(minflow, cap[u][v] - flow[u][v]); } return minflow; } // 更新增广路上所有水渠的剩余容量 void updateFlow(int s, int t, int minflow) { for (int v = t; v != s; v = pre[v]) { int u = pre[v]; flow[u][v] += minflow; flow[v][u] -= minflow; // 反向边减去流量 } } // Edmonds-Karp算法求解最大流 void maxFlow(int s, int t) { while (bfs(s, t)) { int minflow = getMinFlow(s, t); updateFlow(s, t, minflow); maxflow += minflow; } } int main() { cin >> m >> n; memset(cap, 0, sizeof(cap)); memset(flow, 0, sizeof(flow)); for (int i = 0; i < n; i++) { int u, v, w; cin >> u >> v >> w; cap[u][v] += w; } maxFlow(1, m); cout << maxflow << endl; return 0; } ``` 注意,这里的cap数组表示的是池塘之间的水渠容量,而不是每条水渠的容量。因此,在读入水渠信息时,需要将水渠的容量累加到对应的cap元素中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UQI-LIUWJ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值