Luogu P2764 Problem Solving Report

P2764 Minimum path coverage problem

Problem Description:

Given a directed graph \(G=(V,E)\) . Let \(P\) be a set of simple paths (disjoint vertices ) of \(G\) . If every vertex in \ (V\) is exactly on one path of \(P\), then \(P\) is said to be a path cover of \(G\) . The path in \(P\) can start from any vertex of \(V\) , and the length is also arbitrary, in particular, it can be \(0\) . The minimum path coverage of \(G\ ) is the path coverage of \(G\) that contains the fewest paths. Design an efficient algorithm to find the minimum path coverage of a directed acyclic graph \(G\) .

Hint: set \(V={1,2,.... ,n}\) , construct the network \(G_1=(V_1,E_1)\)

如下:
\(V_1=\{x_1,x_2,...,x_n\}\cup\{y_1,y_2,...y_n\}\)
\(E_1=\{(x_0,x_i):i\in V\}\cup\{(y_0,y_i):i\in E \}\cup\{(x_i,y_j):(i,j)\in E\}\)

That is, the capacity of each edge is 1. Find the network \(G_1\) maximum flow.

Input and output format

Input format:

The first line of the file has 2 positive integers \(n\) and \(m\) . \(n\) is the number of vertices of the given directed acyclic graph \(G\) , \(m\) is the number of edges \(G\) . The next \(m\) lines, each line has \(2\) positive integers \(i\) and \(j\) , representing a directed edge \((i,j)\) .

Output format:

From line 1, output one path per line. The last line of the file is the minimum number of paths.

illustrate

\(1<=n<=150,1<=m<=6000\)
by @zhouyonglong SPJ


In fact, the instructions are very clear.

Here is an explanation in my own perceptual language.

Description: Split each point in the graph into two and divide it into two graphs. Connect to the original edge. Running bipartite graph matching, the minimum number of paths = total number of points - maximum number of matches .

Explanation:
It is not difficult to find that the number of paths + the number of edges in the path set = the total number of points.(peptide chain)

With the total number of points unchanged, we can convert to the maximum number of edges.

For each point \(i\) in the original image , it can be divided into the following four cases.

In order to make the number of edges as large as possible, we should make case (3) occur more often.

In these cases, a point can only be poked at a certain point at most, and it can only be poked by at most one point.

So,Delivery?match?

Let's see what the bipartite graph we are running is, isn't it very clear~


CODE:

#include <cstdio>
#include <cstring>
const int N=160;
int n,m;
struct edge
{
    int to,next;
}g[N*N];
int head[N],cnt=0;
void add(int u,int v)
{
    g[++cnt].to=v;
    g[cnt].next=head[u];
    head[u]=cnt;
}
int used[N],match[N];
bool m_find(int u)
{
    for(int i=head[u];i;i=g[i].next)
    {
        int v=g[i].to;
        if(!used[v])
        {
            used[v]=1;
            if(!match[v]||m_find(match[v]))
            {
                match[v]=u;
                return true;
            }
        }
    }
    return false;
}

void dfs(int now)
{
    if(!match[now]) {printf("%d ",now);return;}
    dfs(match[now]); printf("%d ",now);
}

int main()
{
    scanf("%d%d",&n,&m);
    int u,v;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&u,&v);
        add(u,v);
    }
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        memset(used,0,sizeof(used));
        if(m_find(i)) ans++;
    }
    memset(used,0,sizeof(used));
    for(int i=1;i<=n;i++)
        used[match[i]]=1;
    for(int i=1;i<=n;i++)
        if(!used[i])
        {dfs(i);printf("\n");}
    printf("%d\n",n-ans);
    return 0;
}

2018.5.6

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325382009&siteId=291194637