1. 程式人生 > >【Bzoj1927】星際競速(費用流)

【Bzoj1927】星際競速(費用流)

read lin logs esp clu blog using tdi ++

Description

題意:給定n個點m條邊的無向圖,只能從編號小的到編號大的,且要求經過所有點剛好一次,而且可以從任意點瞬移到i號點並花費代價Ai,求最小代價。

n<=800,m<=15000

Solution

Code

#include <cstdio>
#include <algorithm>
#include <queue> 
#define N 2010
#define Inf 0x7fffffff
using namespace std;

struct info{int to,nex,f,c;}e[N*100];
int n,m,T,S,tot,nodes,head[N],Ans;
int
dis[N],fr[N]; bool vis[N]; inline void Link(int u,int v,int f,int c){ e[++tot].to=v;e[tot].nex=head[u];head[u]=tot;e[tot].f=f;e[tot].c=c; e[++tot].to=u;e[tot].nex=head[v];head[v]=tot;e[tot].f=0;e[tot].c=-c; } inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'
){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } inline void Init(){ n=read(),m=read(); S=0,T=n*2+1;tot=1; for(int i=1;i<=n;++i){ int t=read(); Link(S,i,1,0); Link(i+n,T,1
,0); Link(S,i+n,1,t); } while(m--){ int u=read(),v=read(),w=read(); if(u>v) swap(u,v); Link(u,v+n,1,w); } } queue<int> q; bool spfa(){ for(int i=0;i<=T;++i)dis[i]=Inf; while(!q.empty()) q.pop(); dis[0]=0,q.push(0),vis[0]=1; while(!q.empty()){ int u=q.front();q.pop(); //vis[u]=0; for(int i=head[u];i;i=e[i].nex){ int v=e[i].to; if(e[i].f&&dis[v]>dis[u]+e[i].c){ dis[v]=dis[u]+e[i].c; fr[v]=i; if(!vis[v]){vis[v]=1;q.push(v);} } } vis[u]=0; } if(dis[T]==Inf) return 0; return 1; } void mcf(){ int x=Inf; for(int i=fr[T];i;i=fr[e[i^1].to]) x=min(x,e[i].f); for(int i=fr[T];i;i=fr[e[i^1].to]){ Ans+=x*e[i].c; e[i].f-=x; e[i^1].f+=x; } } int main(){ Init(); while(spfa()) mcf(); printf("%d\n",Ans); return 0; }

【Bzoj1927】星際競速(費用流)