传送门
不是很懂为什么现在找得到的题解全部写单纯形,明明对偶之后是一个很明显的最大费用可行流。。。
题解:
首先,由贪心可知,树边权值不会减少,非树边权值不会增加。
设树边集合为 T T T,非树边集合为 E E E。
设 d i d_i di表示第 i i i条边的变化量。设 j cover i j\text{ cover }i j cover i表示一条非树边 j j j两端对应的树上路径中包含树边 i i i。
由最小生成树的性质,则我们可以列出如下线性规划:
l
i
m
i
t
s
:
d
i
+
d
j
≥
w
i
−
w
j
,
∀
i
∈
T
,
j
∈
E
,
j
cover
i
d
i
≥
0
m
i
n
i
m
i
z
e
:
∑
i
∈
T
b
i
d
i
+
∑
i
∈
E
a
i
d
i
\begin{aligned} limits:&&&&&&d_i+d_j&\geq w_i-w_j,\forall i\in T,j\in E,j\text{ cover }i\\ &&&&&&d_i&\geq0\\ minimize:&&&&&&\sum_{i\in T}b_id_i&+\sum_{i\in E}a_id_i \end{aligned}
limits:minimize:di+djdii∈T∑bidi≥wi−wj,∀i∈T,j∈E,j cover i≥0+i∈E∑aidi
转对偶:
l i m i t s : ∑ j ∈ E , j cover i c i , j ≤ b i , ∀ i ∈ T ∑ i ∈ T , j cover i c i , j ≤ a j , ∀ j ∈ E c i , j ≥ 0 m a x m i z e : ∑ i ∈ T , j ∈ E j cover i ( w i − w j ) c i , j \begin{aligned} limits:&&&&&&\sum_{j\in E,j\text{ cover }i}c_{i,j}&\leq b_i,\forall i\in T\\ &&&&&&\sum_{i\in T,j\text{ cover }i}c_{i,j}&\leq a_j,\forall j\in E\\ &&&&&&c_{i,j}&\geq 0\\ maxmize:&&&&&&\sum_{\begin{aligned}i\in T,j\in E\\j\text{ cover }i\end{aligned}}(w_i&-w_j)c_{i,j} \end{aligned} limits:maxmize:j∈E,j cover i∑ci,ji∈T,j cover i∑ci,jci,ji∈T,j∈Ej cover i∑(wi≤bi,∀i∈T≤aj,∀j∈E≥0−wj)ci,j
然后这个形式是一个二分图最大权多重匹配,直接建图跑最大费用可行流就行了。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define gc get_char
#define cs const
namespace IO{
inline char get_char(){
static cs int Rlen=1<<22|1;
static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
template<typename T>
inline T get(){
char c;T num;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
inline int gi(){return get<int>();}
}
using namespace IO;
using std::cerr;
using std::cout;
typedef std::pair<int,int> pii;
#define fi first
#define se second
namespace NetWork{
cs int N=1e3+7;
int S,T,tot;
struct edge{int to,rev,cap,w;};
typedef std::vector<edge>::iterator iter;
std::vector<edge> G[N];iter cur[N];
inline void adde(int u,int v,int cap,int cost){
G[u].push_back((edge){v,G[v].size(),cap,cost});
G[v].push_back((edge){u,G[u].size()-1,0,-cost});
}
int dis[N],vis[N];
inline bool SPFA(){
memset(dis+1,-0x3f,sizeof(int)*tot);
memset(vis+1,0,sizeof(int)*tot);
std::queue<int> q;q.push(S);dis[S]=0;
while(!q.empty()){
int u=q.front();q.pop();vis[u]=false;cur[u]=G[u].begin();
for(auto e:G[u])if(e.cap&&dis[e.to]<dis[u]+e.w){
dis[e.to]=dis[u]+e.w;
if(!vis[e.to])q.push(e.to),vis[e.to]=true;
}
}
return dis[T]>0;
}
int tot_cost,tot_flow;
int dfs(int u,int flow){
if(u==T){
tot_cost+=flow*dis[T];
tot_flow+=flow;
return flow;
}
vis[u]=true;int ans=0;
for(iter &e=cur[u];e!=G[u].end();++e)
if(e->cap&&!vis[e->to]&&dis[e->to]==dis[u]+e->w){
int delta=dfs(e->to,std::min(flow-ans,e->cap));
if(!delta){vis[e->to]=true;continue;}
e->cap-=delta;
G[e->to][e->rev].cap+=delta;
if((ans+=delta)==flow)break;
}
vis[u]=false;return ans;
}
inline void work(){
tot_flow=tot_cost=0;
while(SPFA())dfs(S,0x3f3f3f3f);
cout<<tot_cost<<"\n";
}
}
using NetWork::S;
using NetWork::T;
using NetWork::tot;
namespace Graph{
cs int N=3e2+7,M=1e3+7;
int n,m,c1,c2;
int w[M],c[M];pii E[M];
std::vector<pii> G[N];
int fa[N],fa_e[N],d[N];
void dfs(int u,int p,int eid){
fa[u]=p,fa_e[u]=eid;d[u]=d[p]+1;
for(pii e:G[u])if(e.fi!=p)dfs(e.fi,u,e.se);
}
inline void work_path(int u,int v,int eid){
while(u^v){
if(d[u]>d[v])std::swap(u,v);
NetWork::adde(fa_e[v],eid,0x3f3f3f3f,w[fa_e[v]]-w[eid]);
v=fa[v];
}
}
inline void work(){
n=gi(),m=gi();c1=1,c2=n;S=m+1,T=tot=m+2;
for(int re i=1;i<=m;++i){
int u=gi(),v=gi(),val=gi(),f=gi(),a=gi(),b=gi();
if(!f){
E[c2]=pii(u,v);
c[c2]=a,w[c2]=val;++c2;
}
else {
E[c1]=pii(u,v);
G[u].push_back(pii(v,c1));
G[v].push_back(pii(u,c1));
c[c1]=b;w[c1]=val;++c1;
}
}
dfs(1,0,0);
for(int re i=n;i<=m;++i)work_path(E[i].fi,E[i].se,i);
for(int re i=1;i<n;++i)NetWork::adde(S,i,c[i],0);
for(int re i=n;i<=m;++i)NetWork::adde(i,T,c[i],0);
}
}
signed main(){
#ifdef zxyoi
freopen("mst.in","r",stdin);
#endif
Graph::work();
NetWork::work();
return 0;
}
本文探讨了最小生成树(MST)问题与最大费用流之间的联系,通过将MST问题转化为一个最大费用可行流问题,提供了一种新颖的求解策略。文章详细介绍了如何建立线性规划模型,通过求解其对偶问题,最终转化为二分图最大权多重匹配问题,再利用最大费用流算法解决。
1035

被折叠的 条评论
为什么被折叠?



