考试时
PUCK:我们攻克了一个技术问题,现在可以用 c++14 了
结果:评测机发神经吃我100分
T1
T2
T3
T4
没错就是这道吃了我100pts
一眼可以发现是一个很典的最大费用最大流模型,暴力建图
发现边数 \(n^2\) 不可过
注意到曼哈顿距离是两个绝对值构成的
注意到 \(|a|+|b|=\max(a+b,-a+b,a-b,-a-b)\)
于是在男女间设立四个虚拟点代表四种情况就可以了
code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=3005;
const int M=6e6+5;
const int inf= LONG_LONG_MAX;
int n,m,s,t;
struct edge{
int v,nxt,w,x;
}e[M];
int cnt=1,hd[M];
void add(int u,int v,int w,int X){//建边、
e[++cnt]={v,hd[u],w,X},hd[u]=cnt;
e[++cnt]={u,hd[v],0,-X},hd[v]=cnt;
}
int F;
int ans;
int pre[M];
bool vis[M];
int dis[M];
int dt[M];
int upd(int x){int ret=dt[t];
while(x!=s){
if(x==s) break;
e[pre[x]].w-=ret,e[pre[x]^1].w+=ret;
x=e[pre[x]^1].v;
}
return ret;
}
void EK(){
while(1){
for(int i=s;i<=t;i++) vis[i]=0,dis[i]=-inf,dt[i]=inf;
queue<int> Q;
Q.push(s);vis[s]=1;dis[s]=0;
while(!Q.empty()){
int x=Q.front();vis[x]=0;
Q.pop();
for(int i=hd[x];i;i=e[i].nxt){
if(e[i].x+dis[x]>dis[e[i].v] and e[i].w){
pre[e[i].v]=i;dt[e[i].v]=min(dt[x],e[i].w);
dis[e[i].v]=e[i].x+dis[x];
if(!vis[e[i].v]) Q.push(e[i].v),vis[e[i].v]=1;
}
}
}
if(dis[t]==-inf) break;//cerr<<"?";
int nf=upd(t);
ans+=nf,F+=nf*dis[t];
}
}/
int x[N],y[N],c[N];
int t1,t2,t3,t4;
signed main(){
// freopen("offsheet.in","r",stdin);
// freopen("offsheet.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n;s=0,t=2*n+5;
t1=2*n+1,t2=t1+1,t3=t2+1,t4=t3+1;
for(int i=1;i<=n;i++){
cin>>x[i]>>y[i]>>c[i];
add(s,i,c[i],0);
add(i,t1,inf,x[i]+y[i]);
add(i,t2,inf,x[i]-y[i]);
add(i,t3,inf,-x[i]+y[i]);
add(i,t4,inf,-x[i]-y[i]);
}
for(int i=1;i<=n;i++){
int k=i+n;
cin>>x[k]>>y[k]>>c[k];
add(k,t,c[k],0);
add(t1,k,inf,-x[k]-y[k]);
add(t2,k,inf,-x[k]+y[k]);
add(t3,k,inf,x[k]-y[k]);
add(t4,k,inf,+x[k]+y[k]);
}
EK();
cout<<F;
}
标签:cnt,19,2024.8,int,add,test,inf,hd,dis
From: https://www.cnblogs.com/exut/p/18367247