题解 UVA1349 Optimal Bus Route Design
Posted colazcy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解 UVA1349 Optimal Bus Route Design相关的知识,希望对你有一定的参考价值。
Solution UVA1349 Optimal Bus Route Design
题目大意:给定一个带权有向图,选出若干个简单环,使每个点含于且仅含于一个环,并使得边权和最小
分析:既然每个点仅被包含于一个简单环,那么每个点的入度与出度都为\(1\),也就是这个点有且仅有一条入(出)边.但是我们又不能贪心的去选这个点入边/出边中边权最小的一条边,这样选出来的方案可能根本不合法(不能保证每个点都有入边,可能出现一个环加上一条链之类鬼畜的情况)
那么我们回想一下在无权\(DAG\)上我们是怎么做的.每个点既要考虑它的入边,又要考虑它的出边,我们就拆点构造二分图,拆为入点和出点.用最大流来保证除去路径开头的每个点有且仅有一条入边.对于这道题同理,带权有向图上我们只需跑最小费用最大流即可
- 最大流保证每个点都会有入边
- 将容量设为\(1\)保证每个点仅有一条入边
- 最小费用流保证边权之和最小
我们将每个点\(u\)拆为两个点出点\(u'\)和入点\(u\).对于每条边\((u,v)\),我们连边\((u',v)\).容量\(1\),费用为边权即可.然后建立超级源,往拆点后的出点(出点流向入点,所以源点要连向出点)连边,容量\(1\)费用\(0\).超级汇点同理
然后这题就没了,一个\(DAG\)上最小路径覆盖的变式,挺有意思的.注意别写挂就行了
奉上蒟蒻的代码:
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 256;
const int maxm = (maxn * maxn + maxn + maxn) << 1;
struct Edge
int from,to,cap,flow,cost;
Edge() = default;
Edge(int a,int b,int c,int d,int e):from(a),to(b),cap(c),flow(d),cost(e)
Edges[maxm];
int head[maxn],nxt[maxm],tot = 1;
inline void clear()
tot = 1;
memset(head,0,sizeof(head));
memset(nxt,0,sizeof(nxt));
inline void addedge(int from,int to,int cap,int cost)
Edges[++tot] = Edge(from,to,cap,0,cost);
nxt[tot] = head[from];
head[from] = tot;
Edges[++tot] = Edge(to,from,0,0,-cost);
nxt[tot] = head[to];
head[to] = tot;
int a[maxn],d[maxn],inq[maxn],pre[maxn],flow,cost;
inline bool spfa(int s,int t)
memset(pre,0,sizeof(pre));
memset(d,0x3f,sizeof(d));
d[s] = 0;
a[s] = 0x7fffffff;
queue<int> Q;
Q.push(s),inq[s] = 1;
while(!Q.empty())
int u = Q.front();Q.pop(),inq[u] = 0;
for(int i = head[u];i;i = nxt[i])
Edge &e = Edges[i];
if(e.cap > e.flow && d[e.from] + e.cost < d[e.to])
d[e.to] = d[e.from] + e.cost;
a[e.to] = min(a[e.from],e.cap - e.flow);
pre[e.to] = i;
if(!inq[e.to])Q.push(e.to),inq[e.to] = 1;
if(d[t] == 0x3f3f3f3f)return false;
flow += a[t];
cost += a[t] * d[t];
for(int i = pre[t];i;i = pre[Edges[i].from])
Edges[i].flow += a[t],Edges[i ^ 1].flow -= a[t];
return true;
inline void mcmf(int s,int t)
flow = cost = 0;
while(spfa(s,t));
int n;
inline void solve()
clear();
for(int u = 1;u <= n;u++)
int v,d;
while(scanf("%d",&v) && v)
scanf("%d",&d),addedge(u,v + n,1,d);
int s = n + n + 1,t = s + 1;
for(int i = 1;i <= n;i++)
addedge(s,i,1,0);
for(int i = 1;i <= n;i++)
addedge(i + n,t,1,0);
mcmf(s,t);
if(flow != n)printf("N\n");
else printf("%d\n",cost);
int main()
#ifdef LOCAL
freopen("fafa.in","r",stdin);
#endif
while(scanf("%d",&n) && n)
solve();
return 0;
以上是关于题解 UVA1349 Optimal Bus Route Design的主要内容,如果未能解决你的问题,请参考以下文章
UVA1349 Optimal Bus Route Design 拆点法+最小费用最佳匹配
UVa 1349 Optimal Bus Route Design (最佳完美匹配)
UVaLive 3353 Optimal Bus Route Design (最小费用流)
uvalive 3353 Optimal Bus Route Design