Minimum path covering and minimum chain covering Dilworth theorem: minimum chain covering is equal to the longest inverse chain (detailed proof and classical examples)

Posted by hotcigar on Mon, 03 Jan 2022 00:57:13 +0100

1, Minimum path coverage

definition

Minimum path covering means that in a directed acyclic graph, all points in the graph are covered with the least and disjoint simple paths.

solution

① Disassemble each point in the original drawing (disassemble point u into U and u+n);
② Set each edge < u, V > in the original graph to the corresponding edge < u, V + n > in the new graph;
③ Take the point (1 ~ n) as the left part of the bipartite graph and the point (n+1 ~ 2*n) as the right part of the bipartite graph to carry out the maximum matching of the bipartite graph;
④ The minimum number of paths is equal to the total number of points n minus the maximum number of matches.

//Bipartite graph matching can use Hungarian algorithm or Network flow Just.

2, Minimum chain coverage

definition

The difference between minimum chain coverage and minimum path coverage is that minimum chain coverage allows paths to intersect.
Minimum path covering means that in a directed acyclic graph, all points in the graph are covered with the least simple paths that can intersect.

solution

According to** Floyd The idea of passing closure * * passes the connectivity of the graph:

for(int k = 1;k <= n;k++)
for(int i = 1;i <= n;i++)
for(int j = 1;j <= n;j++)
mp[i][j] |= mp[i][k] & mp[k][j];

After the transfer, if the adjacency matrix mp[u][v] == 1, it indicates that it can reach point v from point U.
After this step, we turn the problem into the minimum path coverage, and the n-maximum matching number is the answer.

3, Chain and anti chain

definition

Chain: a chain is a set of points. Any two points u and v in the point set are called a chain if u can reach v or v can reach U.
Inverse chain: an inverse chain is a set of points. Any two points u and v in the point set are called an inverse chain if u cannot reach v and v cannot reach U.

4, Dilworth theorem

1. Dilworth theorem
In short, the minimum chain coverage of a graph is equal to the longest anti chain length. ( Baidu Encyclopedia (I can't understand it at all)

2. Prove
The proof is complex. You can see the detailed proof This article.

5, Classic examples

1. Luogu P1020 [NOIP1999 popularization group] missile interception

Title Link: P1020 [NOIP1999 popularization group] missile interception thinking
The maximum number of intercepting missiles is to find the length of the longest non increasing subsequence; How many interception systems are needed is to find the minimum number of non increasing subsequences, and according to Dilworth theorem, it is equal to the length of the longest rising subsequence.
Why? We can regard the latter less than or equal to the former in the sequence as the former can reach the latter. The mathematical expression is for the sequence a a a. If a i ≥ a j ( i < j ) a_i≥a_j(i < j) ai ≥ aj (i < j), then point i can reach point j, then according to the definition of chain, a non increasing subsequence can be regarded as a chain, and according to the definition of anti chain, the ascending subsequence is an anti chain. According to Dilworth theorem, the minimum chain coverage is equal to the longest anti chain length, so finding the minimum number of non increasing subsequences is equal to finding the length of the longest ascending subsequence.

ac code

#include <iostream>
#include <algorithm>

using namespace std;
const int N = 1010;

int n,a[N],f[N],g[N];

int main()
{
int res = 0;
while(scanf("%d", &a[n])!= EOF)
n++;
for(int i = 0; i < n; i ++ )
{
f[i] = 1;
for(int j = 0; j < i; j ++ )
if(a[j] >= a[i])
f[i] = max(f[i], f[j] + 1);
res = max(res, f[i]);
}
printf("%d\n", res);	//Find the length of the longest non increasing subsequence

int cnt = 0;
for(int i = 0; i < n; i ++ )
{
int k = 0;
while(k < cnt && g[k] < a[i])
k++;
g[k] = a[i];
if(k >= cnt)
cnt++;
}
printf("%d\n", cnt);	//Find the length of the longest ascending subsequence
}

2,Codeforce 1296 E

General idea of the topic
Give you a string s. you can dye each character in s with numbers. It is stipulated that the two adjacent characters can be exchanged only when their colors are different. Find the minimum number of colors required so that the string s can be arranged in dictionary order from small to large after multiple exchanges, and output the dyeing results.

thinking
We can find that when a subsequence of S is a non decreasing subsequence, they have been arranged from small to large, Therefore, the color of this subsequence can be the same (they don't need to exchange, they are already in order), and two non decreasing subsequences must be exchanged, and the colors need to be different. Therefore, we need to find out how many longest non decreasing subsequences the string s can be divided into. According to Dilworth theorem, the longest inverse chain length, that is, the longest descending subsequence length, is the required number of colors, and construct each character The color of is the length of the longest descending subsequence of the current string that ends with it.

ac code

#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
const int N = 2e5+10;
typedef long long LL;

int n,maxn,cnt,ans[N];	//cnt[i] stores the length of the longest descending subsequence ending with the letter I, and ans stores the staining scheme
string s;

int main()
{
cin >> n >> s;
for(int i = 0;i < s.size();i++)	//Loop each character
{
int t = 0;
for(int j = s[i]+1;j <= 'z';j++)	//Loop all letters larger than the current letter, because the current letter can only be added to the letter larger than him, which is the descending subsequence
t = max(t,cnt[j]);	//Find the longest one
cnt[s[i]] = t+1;	//If the longest descending subsequence is added each time, the length ending with the current character is t plus 1
ans[i] = t+1;		//The coloring scheme is the length of the longest descending subsequence ending with the current letter
maxn = max(maxn,t+1);	//Save a maximum value
}
cout << maxn << endl;
for(int i = 0;i < n;i++)
cout << ans[i] << " ";

return 0;
}