码迷,mamicode.com
首页 > 其他好文 > 详细

题解 UVA1349 【Optimal Bus Route Design】

时间:2019-09-12 21:47:37      阅读:85      评论:0      收藏:0      [点我收藏+]

标签:ring   efault   org   sizeof   clear   开头   简单   pre   main   

题目链接

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】

标签:ring   efault   org   sizeof   clear   开头   简单   pre   main   

原文地址:https://www.cnblogs.com/colazcy/p/11515009.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!