Flow coverage of the shortest path problem

Recently liver network flow a little on top
In fact, I do not want to just want water blog title
Blog nonsense before completion
As \ (luo \ gu \) one of the 24 questions the classic network tumors to write a blog of course the
transfer


In the title in the end say what?

There is now a DAG. FIG selected arbitrary paths, each path is selected, the number of +1 point on the path covered, such that all points are covered and any point is covered only once. The number of selected path is a path coverage. The minimum path coverage is the minimum number of paths.

Here is a simple chestnut

clear that the shortest path covering 1

is red hot path

If you give us is a very complex view of how to do?
This path covers the biggest thing is the pair of n-1 Dui? (Elect tree-like things like violence, it has n-1 edges)
we consider path coverage becomes smaller
if we are elected while there are a -> b and b -> c side, then they can be combined into one path, so that the answer -1
course, if there is to be noted that at this time b -> d side, then a -> only from b b - d a selected> -> C and b merge
then the minimum path coverage is to continue consolidation side, it has been incorporated into the merger no longer up

Obviously we have to take this thing and contact the network flow(Otherwise, how network called tumor 24 questions)
Network flow can engage thought bipartite graph matching
then we expect this operation have split point

Split point operation is Gesha

A dot is to be split into the two points and out-points, only the point of the penetration is not, point out not only the degree of penetration.
It means that point out from a side point, while the end point as the edge is even to the point

After completion of the point and the out-point is found that a bipartite graph

With this magical operation, every time we merge one side, is elected a match. We want to merge as many sides, is elected as many matches, which is the maximum matching of bipartite graph

Seeking bipartite graph maximum matching algorithm can use to Hungary this good stuff (also incidentally record the path), but here is the network network tumors of the world community , we consider the use of network flow out.

FIG above have to get built (it is equivalent to get streaming network), the next step is to record the path of cancer

Considering the construction of FIG time point is the point number of real number + n, it may be pretreated YS (map) array, ys [i] for the i-point real number (that is, when i> n when, ys [ i] = in)

Taking into account the principles of the network flow, if the remaining amount (i.e. dis) 0 to one side, then the match We chose this, that is to say the point of attachment to the edge in the same path. So that the output paths can be achieved using dfs. Note that when dfs also consider those reverse side.

A pair of directly attached codes

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
const int inf=214748364;
typedef long long ll;
inline int read()
{
    char ch=getchar();
    int x=0;bool f=0;
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')f=1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return f?-x:x;
}
int n,m,head[409],cnt=1,ans,s,t;
struct E{
    int to,nxt,dis;
}ed[12009];
int dep[409],cur[409];
queue <int> q;
int ys[409];
bool vis[159];
inline void add(int fr,int to,int dis)
{
    cnt++;
    ed[cnt].to=to;
    ed[cnt].dis=dis;
    ed[cnt].nxt=head[fr];
    head[fr]=cnt;
}
inline bool bfs()
{
    for(int i=1;i<=2*n+2;i++)
     dep[i]=0;
    for(int i=1;i<=2*n+2;i++)
     cur[i]=head[i];
    dep[s]=1; 
    q.push(s);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int e=head[u];e;e=ed[e].nxt)
        {
            int v=ed[e].to;
            if(ed[e].dis&&!dep[v])
            {
                dep[v]=dep[u]+1;
                q.push(v);
            }
        }
    }
    return dep[t];
}
int dfs(int now,int in)
{
    if(now==t)return in;
    int out=0;
    for(int e=cur[now];e;e=ed[e].nxt)
    {
        cur[now]=e;
        int v=ed[e].to;
        if(ed[e].dis&&dep[v]==dep[now]+1)
        {
        int ret=dfs(v,min(in,ed[e].dis));
            ed[e].dis-=ret;
            ed[e^1].dis+=ret;
            in-=ret;
            out+=ret;
            if(!in) return out;
        }
    }
    return out;
}
inline void dinic()
{
    int ret;
    while(bfs())
    {
         ret=0;
         while(ret=dfs(s,20000000))ans+=ret;
    }
}
//上面全是网络流
void lj(int u)//路径不是辣鸡 !!!
{
     printf("%d ",u);
    vis[u]=1;//vis记录是否已经输出
    for(int e=head[u];e;e=ed[e].nxt)
    {
        int v=ed[e].to;
        if(v==s||v==t)continue;//这里注意不考虑自己加的超源,超汇
        if(!ed[e].dis&&!vis[ys[v]])
          lj(ys[v]); 
    }
}
int main()
{
    n=read();m=read();s=n*2+1;t=n*2+2;
    for(int i=1;i<=m;i++)
    {
        int fr=read(),to=read();
        add(fr,to+n,1);add(to+n,fr,0);
    }
    for(int i=1;i<=n;i++)
     add(s,i,1),add(i,s,0);
    for(int i=n+1;i<=2*n;i++)
     add(i,t,1),add(t,i,0);
    for(int i=1;i<=n;i++)
     ys[i]=i;
    for(int i=n+1;i<=2*n;i++)
     ys[i]=i-n;
    ys[s]=s;ys[t]=t;
    dinic();
    ans=n-ans;
    for(int i=1;i<=n;i++)//这里就不从超源开始考虑了qwq
    {
        if(!vis[i])
        {
            lj(i);
        printf("\n");
        }
    }
    printf("%d",ans);
}

Guess you like

Origin www.cnblogs.com/lcez56jsy/p/11406174.html