题解 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

UVA 10304 Optimal Binary Search Tree

UVA10304 Optimal Binary Search Tree最优排序二叉树