首页 > 其他分享 >网络流24题-P2764 最小路径覆盖问题

网络流24题-P2764 最小路径覆盖问题

时间:2022-10-07 19:11:57浏览次数:84  
标签:24 head return int 路径 flow P2764 dis

P2764 最小路径覆盖问题

https://www.luogu.com.cn/problem/P2764

题意

给你一个含有n个点的DAG 问你最小有多少条路径(顶点不相交)可以覆盖整个图的所有点

思路

我们先将每个点设为一条路径 然后将每个点拆成两个点 流出点和流入点
让源点根流出点连边 流入点和汇点连边
根据给出的图 建立相应的边 \(u -> v + n\)流量置为1
如果u 和 v 之间有流量流过就说明以u和v为端点的两条路径可以合并
跑最大流 即原n条路径最多可以被合并多少条
n - 最大流即最后的答案
正确性: 应为源点给每个结点都只有1的流量 所以每个结点只能和一条其他路径合并 即这与即使一个点有多个儿子这个点也只能和一个儿子在同一条路径中对应

#include<bits/stdc++.h>
#define ll long long
#define all(a) a.begin(),a.end()
using namespace std;

const int N = 3e5 + 5;
const int M = 1e6 + 1;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;

int n, m;
int s, t, vtot;
int head[N], cur[N];
int dis[N], etot, tot;
int vis[200][200];
vector<int>g[N];
int in[N];
struct edge {
	int v, nxt;
	int f;
}e[M * 2];
//复杂度 O(n^2*m)
//存图用前向星比较方便 有边的信息 
void addedge(int u, int v, int f) {
	//边序号从零开始
	e[etot] = { v, head[u], f }; head[u] = etot++;
	e[etot] = { u, head[v], 0 }; head[v] = etot++;
}

//s到t是否还有路径
bool bfs() {
	for (int i = 1; i <= vtot; i++) {
		dis[i] = 0;
		cur[i] = head[i];
	}
	queue<int>q;
	q.push(s); dis[s] = 1;
	while (!q.empty()) {
		int u = q.front(); q.pop();
		for (int i = head[u]; ~i; i = e[i].nxt) {
			//有剩余流量且未被访问过
			if (e[i].f && !dis[e[i].v]) {
				int v = e[i].v;
				dis[v] = dis[u] + 1;
				if (v == t) return true;
				q.push(v);
			}
		}
	}
	return false;
}

//找最优路径
int dfs(int u, int m) {
	if (u == t) return m;
	int flow = 0;
	//cur[]当前弧优化 保证增广过了不再增广
	for (int i = cur[u]; ~i; cur[u] = i = e[i].nxt) {
		//如果流量还有剩余 且该边方向是对的
		if (e[i].f && dis[e[i].v] == dis[u] + 1) {
			int f = dfs(e[i].v, min(m, e[i].f));
			e[i].f -= f;
			e[i ^ 1].f += f;
			m -= f;
			flow += f;
			if (!m) break;//保证复杂度
		}
	}
	if (!flow) dis[u] = -1;
	return flow;
}

int dinic() {
	int flow = 0;
	while (bfs()) flow += dfs(s, INF);
	return flow;
}

void init(int s_, int t_, int vtot_) {
	s = s_;
	t = t_;
	vtot = vtot_;
	for (int i = 1; i <= vtot; i++) head[i] = -1;
}

void dfs(int x) {
	cout << x << " ";
	for (auto to : g[x]) {
		if (!vis[x][to]) {
			dfs(to);
			vis[x][to] = 1;
			break;
		}
	}
}

pair<int, int>E[N];
void solve() {
	cin >> n >> m;
	for (int i = 1, u, v; i <= m; i++) {
		cin >> u >> v;
		E[i] = { u, v };
	}

	init(n * 2 + 1, n * 2 + 2, n * 2 + 2);
	for (int i = 1; i <= n; i++) {
		addedge(s, i, 1);
		addedge(i + n, t, 1);
	}

	vector<pair<int, pair<int, int>>>ve;
	for (int i = 1; i <= m; i++) {
		ve.push_back({ etot, E[i] });
		addedge(E[i].first, E[i].second + n, 1);
	}

	ll ans = dinic();
	for (auto x : ve) {
		if (e[x.first].f == 0) {
			g[x.second.first].push_back(x.second.second);
			in[x.second.second]++;
		}
	}

	for (int i = 1; i <= n; i++) {
		if (!in[i]) {
			dfs(i);
			cout << "\n";
		}
	}

	cout << n - ans << "\n";
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    int _t = 1;
    //cin >> _t;
    while (_t--)
        solve();
    return 0;
}

标签:24,head,return,int,路径,flow,P2764,dis
From: https://www.cnblogs.com/yaqu-qxyq/p/16760445.html

相关文章

  • P2467 地精部落 题解
    P2467地精部落题解比较恶心的一道线性dp。要求1~N的排列,满足a[i-1]<a[i]>a[i+1]或a[i-1]>a[i]<a[i+1],求这样的排列的个数。既然是线性dp,那么状态一定和长度有关,一维的......
  • Hexo 图片上传之 hexo-asset-image 路径编译 BUG
    这个BUG的来源于是因为博主想在hexo当中进行本地查看的时候发现图片加载全部未显示,然后我就查看控制台编译的结果发现,路径如下:updatelinkas:-->/.com/06/01/vim/1561......
  • 网络流24题 -洛谷 P2762 太空飞行计划问题
    P2762太空飞行计划问题题意给你n个实验m个仪器(原题中n和m反了一下)第i个实验会给一个赞助费\(c[i]\)每个实验都有相应的实验仪器买第m个实验器材要\(c_2[i]\)的钱问......
  • 永远的曼巴精神 | 从8号到24号到Mamba Out
    转眼间,一年过去了!从你披上八号就爱上你了,看到你和Shaquille三连冠,看到你以一己之力带领我湖进入季后赛,看到你含泪说“MambaOut”!你整个生涯给我们带来了无数的精彩瞬间。5......
  • 王道-求关键路径步骤
    王道-关键路径课件总结    知识点若关键活动耗时增加,则整个工程的工期将增长缩短关键活动的时间,可以缩短整个工程的工期当缩短到一定程度时,关键活......
  • 2.3 遍历指定路径下的文件及子文件夹下的文件
    #importoslst=os.scandir()forfileinlst:print(file,type(file),file.name,file.path,file.is_dir())#运行输出<DirEntry'demo1.py'><class'nt.DirE......
  • 2.2 课堂案例_输出当前路径下所有文件及文件夹
    # listdir(path)返回指定目录下的文件和信息 ,os.listdir()。(注意:返回的是str类型)importosprint(os.listdir())#listdir(path)......
  • 2.1 os模块简介_路径操作
    #os模块简介  ##os模块     ###Python标准库      ###和操作系统有关的操作      ###创建、移动、复制文件和文件夹     ......
  • 最短路径问题---Dijkstra算法详解
    0.最短路径问题介绍问题解释:从图中的某个顶点出发到达另外一个顶点的所经过的边的权重和最小的一条路径,称为最短路径1.Dijkstra算法介绍算法特点:迪科斯彻算法使用......
  • 120-24-ZooKeeper 状态同步全流程源码分析_ev
                         ......