UVA1349 Optimal Bus Route Design 拆点法+最小费用最佳匹配

Posted 天道酬勤007

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVA1349 Optimal Bus Route Design 拆点法+最小费用最佳匹配相关的知识,希望对你有一定的参考价值。

 

/**
题目:UVA1349 Optimal Bus Route Design
链接:https://vjudge.net/problem/UVA-1349
题意:lrj入门经典P375
给n个点(n<=100)的有向带权图,找若干个有向圈,每个点恰好属于一个圈。要求权和尽量小。注意即使(u,v)
和(v,y)都存在,他们的权值也不一定相同。
思路:拆点法+最小费用最佳完美匹配。
如果每个点都有一个唯一的后继(不同的点没有相同的后继点,且只有一个后继),那么每个点一定恰好属于一个圈。
联想到二分图匹配。
(u,v) 表示 u->v有向边。
左边一侧全是u,右边一侧全是v。
u与若干个v有指向关系u->v。

每一个点都扮演着u,v的指向位置关系。指向别的点,被别的点指向,都是唯一性。

对每一个点拆分成两个点,前者指向别的点(作为u),后者被别的点指向(作为v)。

新建源点s,指向所有的u。 新建汇点t,被所有的v指向。容量为1,花费为0.

假设点X,拆分成Xu,Xv。
如果(X,Y)。 那么让Xu指向Yv.(s->Xu->Yv->t)

然后求解最小费用最佳完美匹配。

拆分点的方法:对于点k,可以拆分成2*k,2*k+1.
如果从s出发的流都是满载,那么存在最佳完美匹配。
*/ #include<iostream> #include<cstring> #include<vector> #include<map> #include<cstdio> #include<algorithm> #include<queue> using namespace std; const int INF = 0x3f3f3f3f; typedef long long LL; const int N = 210; struct Edge{ int from, to, cap, flow, cost; Edge(int u,int v,int c,int f,int w):from(u),to(v),cap(c),flow(f),cost(w){} }; struct MCMF{ int n, m; vector<Edge> edges; vector<int> G[N]; int inq[N]; int d[N]; int p[N]; int a[N]; void init(int n){ this->n = n; for(int i = 0; i <= n; i++) G[i].clear(); edges.clear(); } void AddEdge(int from,int to,int cap,long long cost){ edges.push_back(Edge(from,to,cap,0,cost)); edges.push_back(Edge(to,from,0,0,-cost)); m = edges.size(); G[from].push_back(m-2); G[to].push_back(m-1); } bool BellmanFord(int s,int t,int &flow,long long &cost){ for(int i = 0; i <= n; i++) d[i] = INF; memset(inq, 0, sizeof inq); d[s] = 0; inq[s] = 1; p[s] = 0; a[s] = INF; queue<int> Q; Q.push(s); while(!Q.empty()){ int u = Q.front(); Q.pop(); inq[u] = 0; for(int i = 0; i < G[u].size(); i++){ Edge& e = edges[G[u][i]]; if(e.cap>e.flow&&d[e.to]>d[u]+e.cost){ d[e.to] = d[u]+e.cost; p[e.to] = G[u][i]; a[e.to] = min(a[u],e.cap-e.flow); if(!inq[e.to]) {Q.push(e.to); inq[e.to] = 1;} } } } if(d[t]==INF) return false; flow += a[t]; cost += (long long)d[t]*(long long)a[t]; for(int u = t; u!=s; u = edges[p[u]].from){ edges[p[u]].flow+=a[t]; edges[p[u]^1].flow-=a[t]; } return true; } int MincostMaxflow(int s,int t,long long &cost){ int flow = 0; cost = 0; while(BellmanFord(s,t,flow,cost)); return flow; } }; int n; int main() { while(scanf("%d",&n)==1&&n){ int s, t; s = 1, t = 2*n+2; MCMF mcmf; mcmf.init(t); ///s -> front for(int i = 1; i <= n; i++) mcmf.AddEdge(s,2*i,1,0); ///back -> t for(int i = 1; i <= n; i++) mcmf.AddEdge(2*i+1,t,1,0); ///front -> back for(int i = 1; i <= n; i++){ int u = i, v, w; while(scanf("%d",&v)==1&&v){ scanf("%d",&w); mcmf.AddEdge(2*u,2*v+1,1,w); } } long long cost; int flow = mcmf.MincostMaxflow(s,t,cost); if(flow==n){ printf("%lld\n",cost); }else printf("N\n"); } 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最优排序二叉树