其他分享
首页 > 其他分享> > P2469 [SDOI2010]星际竞速

P2469 [SDOI2010]星际竞速

作者:互联网

pro:
https://www.luogu.com.cn/problem/P2469

sol:
发现这个模型和最小路径覆盖有着密切的联系

考虑最小路径覆盖是怎么实现的

一开始用n条长度为1的路径去覆盖n个点

使初始答案为n

每个点拆成入点和出点

对于原图每条边x--->y

然后x的出点和y的入点连边

跑二分图匹配

求最大流flow

则ans=n-flow

因为每匹配两条边就等价于把x所在的路径和y所在路径连接在一起

答案应该-1

再考虑本题

还是先考虑n条路径的情况

答案显然为\(\sum_{i=1}^n a_i\)

然后考虑连接两条路径时能省掉多少代价

发现新增了边权\(w\),减少了新开一条路径的费用\(a_y\)

因此这个问题和最小路径类似

只不过不在是简单的二分图最大匹配

而是变成了一个带权二分图最大匹配

这个玩意显然就是个最大费用流

冲就完事了

#include<bits/stdc++.h>
#define N 11000
#define M 110000
#define eps 1e-7
#define inf 1e12
#define db double
#define ll long long
#define ldb long double
#define ull unsigned long long
using namespace std;
inline ll read()
{
	char ch=0;
	ll x=0,flag=1;
	while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;}
	while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0',ch=getchar();}
	return x*flag;
}
struct edge
{
	ll to,nxt,flow,w;
}e[M];
ll num,head[N];
inline void add(ll x,ll y,ll w,ll z)
{
	e[++num]=(edge){y,head[x],w,+z};head[x]=num;
	e[++num]=(edge){x,head[y],0,-z};head[y]=num; 
}
bool in_queue[N];
ll n,m,s,t,dis[N],pre[N],last[N],flow[N];
queue<ll>q;			
bool spfa()
{
	for(ll i=0;i<=t;i++)dis[i]=-inf,flow[i]=+inf;
	dis[s]=0;q.push(s);in_queue[s]=true;
	while(!q.empty())
	{
		ll x=q.front();q.pop();in_queue[x]=false;
		for(ll i=head[x];i!=-1;i=e[i].nxt)
		{
			ll to=e[i].to;
			if(e[i].flow&&dis[to]<dis[x]+e[i].w)
			{
				pre[to]=x;last[to]=i;
				dis[to]=dis[x]+e[i].w;
				flow[to]=min(flow[x],e[i].flow);
				if(!in_queue[to])q.push(to),in_queue[to]=true;
			}
		}
	}
	return dis[t]>0;
}
void dfs(ll x)
{
	if(x==s)return;
	ll i=last[x];
	e[i].flow-=flow[t];
	e[i^1].flow+=flow[t];
	dfs(pre[x]);
}
ll a[N];
int main()
{
	n=read();m=read();s=2*n+1;t=2*n+2;
	num=-1;memset(head,-1,sizeof(head));
	ll ans=0;
	add(s,t,+inf,0); 
	for(ll i=1;i<=n;i++)
	{
		a[i]=read();
		add(s,i,1,0);
		add(i+n,t,1,0);
		ans+=a[i];
	}
	for(ll i=1;i<=m;i++)
	{
		ll x=read(),y=read(),z=read();
		if(x>y)swap(x,y);
		if(a[y]-z>0)add(x,y+n,1,a[y]-z);
	}
	while(spfa())ans-=dis[t]*flow[t],dfs(t);
	printf("%lld",ans);
	return 0;
}

标签:ch,竞速,ll,路径,flow,long,SDOI2010,P2469,define
来源: https://www.cnblogs.com/Creed-qwq/p/13774275.html