[题解] LuoguP2764 最小路径覆盖问题

传送门

好久没做网络流方面的题发现自己啥都不会了qwq

题意:给一张有向图,让你用最少的简单路径覆盖所有的点。

考虑这样一个东西,刚开始,我们有\(n\)条路径,每条路径就是单一的一个点,那么我们的目的就是进行若干次操作将路径两两合并,这样对于一个以节点\(x\),它作为路径的端点最多被合并两次(一次连出边一次连入边)。

于是考虑二分图,将点\(x\)炸成两个点\(x_0,x_1\),\(x_0\)表示\(x\)连出去的出边,\(x_1\)表示\(x\)连进来的入边。那么对于图上一条\(u \rightarrow v\)的路径,在\(u_0,v_1\)之间连一条边,表示合并一条\(u\)为端点的路径和一条\(v\)为端点的路径。

这样,在合法的情况下最大的合并次数就是这张二分图的最大匹配数。

最小的路径条数就是\(n-\)最大匹配。匈牙利或者网络流啥的求出最大匹配,然后打印方案的话就对整张图照着最大匹配中的边\(Dfs\)一遍。

网络流的代码 还是感觉匈牙利好写......

#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for (int i=(a);i<(b);++i)
#define per(i,a,b) for (int i=(a)-1;i>=(b);--i)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
typedef double db;
typedef long long ll;
typedef pair<int,int> PII;
typedef vector<int> VI;

const int N=1e5+10,INF=0x3f3f3f3f;

struct Dinic {
    int n,S,T;
    int to[N<<1],nxt[N<<1],fst[N],cap[N<<1],flow[N<<1],cnt=0;

    inline void ade(int x,int y,int w) {
        to[++cnt]=y,cap[cnt]=w,flow[cnt]=0;
        nxt[cnt]=fst[x],fst[x]=cnt;
    }
    inline void addedge(int x,int y,int w) {ade(x,y,w),ade(y,x,0);}

    int d[N],q[N];
    bool bfs() {
        rep(i,0,n+1) d[i]=0;
        int tn=1; q[0]=S;
        d[S]=1;
        rep(_,0,tn) {
            int u=q[_];
            for(int i=fst[u];i;i=nxt[i]) {
                int v=to[i];
                if(d[v]==0&&cap[i]>flow[i]) {
                    d[v]=d[u]+1;
                    q[tn++]=v;
                }
            }
        }
        return d[T]!=0;
    }

    int cur[N];
    int dfs(int x,int ag) {
        if(x==T||ag==0) return ag;
        for(int &i=cur[x];i;i=nxt[i]) {
            int v=to[i];
            if(cap[i]>flow[i]&&d[v]==d[x]+1) {
                int out=dfs(v,min(ag,cap[i]-flow[i]));
                if(out) {
                    flow[i]+=out;
                    flow[i^1]-=out;
                    return out;
                }
                else d[v]=0;
            }
        }
        return 0;
    }

    int Maxflow() {
        int ans=0,out=0;
        while(bfs()) {
            rep(i,0,n+1) cur[i]=fst[i];
            while(out=dfs(S,1e9)) ans+=out;
        }
        return ans;
    }

    void init(int tn,int s,int t) {
        S=s,T=t,n=tn;
        rep(i,0,n+1) fst[i]=0;
        cnt=1;
    }
}flow;

#define IDL(x) (x)
#define IDR(x) ((x)+n)
#define NODE(x) ((x)<=n?(x):(x)-n)
int n,m;
int vis[233][233],mark[N];
VI g[N];

void dfs(int x) {
    printf("%d ",x);
    mark[x]=1;
    for(auto v:g[x]) if(vis[x][v])
        dfs(v);
}

int main() {
    scanf("%d%d",&n,&m);
    const int S=n*2+1,T=n*2+2;
    flow.init(n*2+5,S,T);
    rep(i,1,n+1) flow.addedge(S,IDL(i),1),flow.addedge(IDR(i),T,1);
    rep(i,0,m) {
        int x,y; scanf("%d%d",&x,&y);
        flow.addedge(IDL(x),IDR(y),INF);
        g[x].pb(y);
    }
    int ans=n-flow.Maxflow();
    rep(i,2,flow.cnt+1) if(flow.flow[i]==1)
        vis[NODE(flow.to[i^1])][NODE(flow.to[i])]=1;
    rep(i,1,n) if(!mark[i]) dfs(i),puts("");
    printf("%d\n",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/wxq1229/p/12350733.html

时间: 2024-10-24 14:55:21

[题解] LuoguP2764 最小路径覆盖问题的相关文章

[FZYZOJ 1356] 8-3 最小路径覆盖问题

P1356 -- 8-3 最小路径覆盖问题 时间限制:1000MS 内存限制:131072KB Description 给定有向图G=(V,E).设P 是G 的一个简单路(顶点不相交)的集合.如果V 中每个顶点恰好在P 的一条路上,则称P是G 的一个路径覆盖.P 中路径可以从V 的任何一个顶点开始,长度也是任意的,特别地,可以为0.G 的最小路径覆盖是G 的所含路径条数最少的路径覆盖.设计一个有效算法求一个有向无环图G 的最小路径覆盖. Input Format 第1 行有2个正整数n和m.n是

hdu 1151 Air Raid 最小路径覆盖

Air Raid Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=1151 Description Consider a town where all the streets are one-way and each street leads from one intersection to another. It is also known that starting

POJ1422 Air Raid 【DAG最小路径覆盖】

Air Raid Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 6763   Accepted: 4034 Description Consider a town where all the streets are one-way and each street leads from one intersection to another. It is also known that starting from an i

uva1201 DAG 最小路径覆盖,转化为 二分图

大白例题P356 你在一座城市里负责一个大型活动的接待工作.你需要去送m个人从出发地到目的地,已知每个人的出发时间出发地点,和目的地点,你的任务是用尽量少的出租车送他们,使得每次出租车接客人,至少能提前一分钟达到他所在的位置,城市为网格 (x1,y1) ===>(x2,y2) 需要|x1-x2|+|y1-y2|分钟 题解: 本题的模型是DAG的最小路径覆盖.所谓最小路径覆盖就是在图中找尽量少的路径,使得每个结点恰好在一条路径上(话句话说,不同路径不能有公共点).单独的节点也可以作为一条路径. 本

洛谷 P2764 LibreOJ 6002 最小路径覆盖问题

题目描述 «问题描述: 给定有向图G=(V,E).设P 是G 的一个简单路(顶点不相交)的集合.如果V 中每个顶点恰好在P 的一条路上,则称P是G 的一个路径覆盖.P 中路径可以从V 的任何一个顶点开始,长度也是任意的,特别地,可以为0.G 的最小路径覆盖是G 的所含路径条数最少的路径覆盖.设计一个有效算法求一个有向无环图G 的最小路径覆盖.提示:设V={1,2,.... ,n},构造网络G1=(V1,E1)如下: 每条边的容量均为1.求网络G1的( 0 x , 0 y )最大流. «编程任务:

poj 2594(最小路径覆盖)

题意:有n个点需要探索(编号从1到n),然后给出图上有m条有向边,问最少选择多少个点能遍历所有的点.注意走过的点可以重复再走. 题解:二分图求最小路径覆盖问题中点是不可以重复的,但这道题说可以重复,所以做法是可以把走过的点跳过,间接相连的点改为直接相连就可以跳过了. 特殊样例 5 4 1 2 2 3 4 2 2 5 #include <stdio.h> #include <string.h> const int N = 505; int n, m, g[N][N], vis[N],

POJ3020 Antenna Placement(二分图最小路径覆盖)

The Global Aerial Research Centre has been allotted the task of building the fifth generation of mobile phone nets in Sweden. The most striking reason why they got the job, is their discovery of a new, highly noise resistant, antenna. It is called 4D

最小路径覆盖问题

byvoid好神啊Orz 摘自byvoid的题解 [问题分析] 有向无环图最小路径覆盖,可以转化成二分图最大匹配问题,从而用最大流解决. [建模方法] 构造二分图,把原图每个顶点i拆分成二分图X,Y集合中的两个顶点Xi和Yi.对于原图中存在的每条边(i,j),在二分图中连接边(Xi,Yj).然后把二分图最大匹配模型转化为网络流模型,求网络最大流. 最小路径覆盖的条数,就是原图顶点数,减去二分图最大匹配数.沿着匹配边查找,就是一个路径上的点,输出所有路径即可. [建模分析] 对于一个路径覆盖,有如

POJ2594:Treasure Exploration(Floyd + 最小路径覆盖)

Treasure Exploration Time Limit: 6000MS   Memory Limit: 65536K Total Submissions: 9794   Accepted: 3975 题目链接:http://poj.org/problem?id=2594 Description: Have you ever read any book about treasure exploration? Have you ever see any film about treasure