有一些敌军据点,有一些能源基地,基地给和它距离小于R的点提供能量。你有一些炮台,摧毁一个据点有两种方法,一种是直接摧毁据点,一种是摧毁给他提供能源的所有基地。用一个炮台摧毁一个目标的代价是欧几里得距离的平方。问你摧毁所有据点的最小代价。
解法:二分图最小点权覆盖。
预处理出摧毁一个基地和一个据点的的最小代价。以据点为X部,源点连流量为摧毁代价的边,基地为Y部,汇点连流量为摧毁代价的边,如果一个基地给一个据点提供能量,在两部之间连接流量为无穷的边。从源点向汇点求最小割(最大流)即可。
#include <bits/stdc++.h>
#define maxn 1009
#define maxm 2000009
#define INF 1e9
using namespace std;
struct Edge
{
int v,next,cap;
}edge[maxm];
int head[maxn],h[maxn],gap[maxn],tot,n,src,des,N;
inline void addedge(int u,int v,int cap)
{
edge[tot].v=v;
edge[tot].cap=cap;
edge[tot].next=head[u];
head[u]=tot++;
edge[tot].v=u;
edge[tot].cap=0;
edge[tot].next=head[v];
head[v]=tot++;
}
int dis(int x1,int y1,int x2,int y2)
{
return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
}
inline int dfs(int u,int cap)
{
if(u==des)return cap;
int minh=n-1;
int lv=cap,d;
for(int e=head[u];e!=-1;e=edge[e].next)
{
int v=edge[e].v;
int w=edge[e].cap;
if(w>0)
{
if(h[v]+1==h[u])
{
d=min(lv,edge[e].cap);
d=dfs(v,d);
edge[e].cap-=d;
edge[e^1].cap+=d;
lv-=d;
if(h[src]>=n)return cap-lv;
if(lv==0)
break;
}
minh=min(minh,h[v]);
}
}
if(lv==cap)
{
--gap[h[u]];
if(gap[h[u]]==0)h[src]=n;
h[u]=minh+1;
++gap[h[u]];
}
return cap-lv;
}
int sap()
{
int res=0;
memset(gap,0,sizeof(gap));
memset(h,0,sizeof(h));
gap[0]=n;
while(h[src]<n)res+=dfs(src,INF);
return res;
}
class GreenWarfare
{
public:int minimumEnergyCost(vector <int> canonX, vector <int> canonY, vector <int> baseX, vector <int> baseY, vector <int> plantX, vector <int> plantY, int energySupplyRadius)
{
int base=baseX.size();
src=0;
memset(head,-1,sizeof(head));tot=0;
for(int i=0;i<base;i++)
{
int cur=INF;
for(int j=0;j<(int)canonX.size();j++)
{
cur=min(cur,dis(canonX[j],canonY[j],baseX[i],baseY[i]));
}
addedge(src,i+1,cur);
}
int plant=plantX.size();
des=base+plant+1;
n=des+1;
for(int i=0;i<plant;i++)
{
int cur=INF;
for(int j=0;j<(int)canonX.size();j++)
{
cur=min(cur,dis(plantX[i],plantY[i],canonX[j],canonY[j]));
}
addedge(base+i+1,des,cur);
}
for(int i=0;i<base;i++)
{
for(int j=0;j<plant;j++)
{
if(dis(baseX[i],baseY[i],plantX[j],plantY[j])<=energySupplyRadius*energySupplyRadius)
{
addedge(i+1,j+base+1,INF);
}
}
}
return sap();
}
};