最小费用最大流:(SPFA求最长路)(下面是一个求二分图最小权重的例题)
将白黑点左右分部,连接所有边,这道题等价于求总边权最小。
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn=609;
const int maxm=2e5+7;
const double epos=1.0e-7;
const int inf=0x3f3f3f3f;
struct Edge{
int v,w,next;
double cost;//花费;
}edge[maxm];
int head[maxn],top;
void init(){
top=0;
memset(head,-1,sizeof(head));
}
void add(int u,int v,int w,double cost){
edge[top].v=v;
edge[top].w=w;
edge[top].cost=cost;
edge[top].next=head[u];
head[u]=top++;
}
double d[maxn];
int incf[maxn];
int pre[maxn];//记录前驱,便于找到最长路的实际方案;
bool vis[maxn];
int s,t;
int maxflow;//最大流;
double ans;//最小费用;
int n,m;
queue<int> q;
bool spfa(){
while(!q.empty()) q.pop();
for(int i=0;i<=2*n+1;++i) d[i]=inf;
memset(vis,0,sizeof(vis));
q.push(s);
d[s]=0,vis[s]=1;
incf[s]=inf;
int u,v;
int w;
while(q.size()){
u=q.front(); q.pop();
vis[u]=0;
for(int i=head[u];i!=-1;i=edge[i].next){
v=edge[i].v;
w=edge[i].w;
if(!w) continue;
if(d[v]>d[u]+edge[i].cost){
d[v]=d[u]+edge[i].cost;
incf[v]=min(incf[u],w);
pre[v]=i;
if(!vis[v]) vis[v]=1,q.push(v);
}
}
}
return d[t]<inf-epos;
}
void updata(){
int u=t;
while(u!=s){
int i=pre[u];
edge[i].w-=incf[t];
edge[i^1].w+=incf[t];
u=edge[i^1].v;
}
maxflow+=incf[t];
ans+=d[t]*incf[t];
}
int x1[maxn],y111[maxn],x2[maxn],y2[maxn];
double juli(double x1,double y111,double x2,double y2){
return sqrt((x1-x2)*(x1-x2)+(y111-y2)*(y111-y2));
}
int main(){
scanf("%d",&n);
s=0,t=2*n+1;
ans=maxflow=0;
memset(incf,0,sizeof(incf));
init();
for(int i=1;i<=n;++i) add(s,i,1,0),add(i,s,0,0),add(i+n,t,1,0),add(t,i+n,0,0);
for(int i=1;i<=n;++i) scanf("%d%d",&x1[i],&y111[i]);
for(int i=1;i<=n;++i) scanf("%d%d",&x2[i],&y2[i]);
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
add(i,j+n,1,juli(x1[i],y111[i],x2[j],y2[j])),add(j+n,i,0,-juli(x1[i],y111[i],x2[j],y2[j]));
while(spfa()) updata();
for(int i=1;i<=n;++i)
for(int j=head[i];j!=-1;j=edge[j].next)
if(edge[j].w==0){
printf("%d\n",edge[j].v-n);
break;
}
return 0;
}
最大费用的话,为求最短路,将d数组设为负无穷,同时spfa中的松弛条件改为<,return的部分改为与负无穷的差值。