[欧拉回路 KM] AOJ 2724 Laser Cutter

存在一种方式等价于存在欧拉回路
对于有向图即入度=出度
所以对所有的线段的起点与终点按距离进行最小权匹配即可

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#define cl(x) memset(x,0,sizeof(x))
#define read(x) scanf("%d",&(x));
using namespace std;

inline double sqr(int x){ return x*x; }

const int N=305;

struct PP{
  int x,y;
  friend double dist(PP A,PP B){
    return sqrt(sqr(A.x-B.x)+sqr(A.y-B.y));
  }
}s[N],t[N];

int n; double w[N][N];
int boy[N]; double sla[N],lx[N],ly[N];
int S[N],T[N];

inline bool match(int u){
  S[u]=1;
  for (int v=1;v<=n;v++){
    if (T[v]) continue;
    if (fabs(lx[u]+ly[v]-w[u][v])<1e-10){
      T[v]=1;
      if (!boy[v] || match(boy[v]))
    return boy[v]=u,1;
    }else
      sla[v]=min(sla[v],lx[u]+ly[v]-w[u][v]);
  }return 0;
}

inline double KM(){
  for (int i=1;i<=n;i++){
    lx[i]=-1<<30;
    for (int j=1;j<=n;j++)
      lx[i]=max(lx[i],w[i][j]);
  }
  for (int i=1;i<=n;i++){
    for (int j=1;j<=n;j++) sla[j]=1<<30;
    while (1){
      cl(S); cl(T); if (match(i)) break;
      double a=1<<30;
      for (int j=1;j<=n;j++) if (!T[j]) a=min(a,sla[j]);
      for (int j=1;j<=n;j++) if (S[j]) lx[j]-=a;
      for (int j=1;j<=n;j++) if (T[j]) ly[j]+=a; else sla[j]-=a;
    }
  }
  double ret=0;  
  for (int i=1;i<=n;i++) if (boy[i]) ret-=w[boy[i]][i];  
  return ret;
}

double ans=0;

int main(){
  freopen("t.in","r",stdin);
  freopen("t.out","w",stdout);
  read(n); read(s[1].x); read(s[1].y);
  for (int i=1;i<=n;i++){
    read(s[i].x); read(s[i].y);
    read(t[i].x); read(t[i].y);
    ans+=dist(s[i],t[i]);
  }
  for (int i=1;i<=n;i++)
    for (int j=1;j<=n;j++)
      w[i][j]=-dist(t[i],s[j]);
  ans+=KM();
  printf("%.10lf\n",ans);
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值