375. 蚂蚁(最大带权匹配)

375. 蚂蚁

首先我们需要将题意转换成我们能处理的意思:

不想交==最短

如此图,a与d,b与c相连则会相交,由于相交所以必有1+2+3+4>5+6,所以a与c,b与d距离最短切不想交

由于相交不然会出现上图的三角形,所以我们控制总和最小,则必不相交...

之后我们跑二分图带权最小即可.

这里用的网络流实现的.

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=210,INF=2e9;
int n,link[N],s,t,incf[N],pre[N],c[N],vis[N],tot=1;
double dis[N];
struct edge{int y,next,v;double c;}a[N*N*N];
struct node{int x,y;}b1[N],b2[N];
inline int read()
{
    int x=0,ff=1;
    char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}
    while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*ff;
}
inline double distanc(int i,int j)
{
    double x=b1[i].x-b2[j].x;
    double y=b1[i].y-b2[j].y;
    //cout<<x<<' '<<y<<endl;
    return sqrt(x*x+y*y);
}
inline void add(int x,int y,int v,double c)
{
    a[++tot].y=y;a[tot].v=v;a[tot].c=c;a[tot].next=link[x];link[x]=tot;
    a[++tot].y=x;a[tot].v=0;a[tot].c=-c;a[tot].next=link[y];link[y]=tot;
}
inline bool spfa()
{
    queue<int>q;q.push(s);
    for(int i=s;i<=t;++i) dis[i]=INF;
    memset(vis,0,sizeof(vis));
    dis[s]=0;incf[s]=INF;vis[s]=1;
    while(!q.empty())
    {
        int x=q.front();q.pop();vis[x]=0;
        for(int i=link[x];i;i=a[i].next)
        {
            int y=a[i].y;
            //if(x==1&&y==2) cout<<a[i].v<<' '<<a[i].c<<endl;
            if(!a[i].v) continue;
            if(dis[y]>dis[x]+a[i].c)
            {
                dis[y]=dis[x]+a[i].c;
                incf[y]=min(incf[x],a[i].v);
                pre[y]=i;
                if(!vis[y]) vis[y]=1,q.push(y);
            }
        }
    }
    if(dis[t]==INF) return false;
    return true;
}
inline void updata()
{
    int x=t,o;
    while(x!=s)
    {
        //cout<<x<<endl;
        if(x>=n+1&&x<=n*2) o=x;
        else if(x>=1&&x<=n) c[x]=o; 
        int i=pre[x];
        a[i].v-=incf[t];
        a[i^1].v+=incf[t];
        x=a[i^1].y;
    }
    
}
int main()
{
    freopen("1.in","r",stdin);
    n=read();
    s=0;t=n<<1|1;
    for(int i=1;i<=n;++i) b1[i].x=read(),b1[i].y=read();
    for(int i=1;i<=n;++i) b2[i].x=read(),b2[i].y=read();
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j) add(i,j+n,1,distanc(i,j));
    //    cout<<distanc(1,1)<<endl;
    for(int i=1;i<=n;++i) add(s,i,1,0);
    for(int i=1;i<=n;++i) add(i+n,t,1,0);
    while(spfa()) updata();
    //cout<<c[1]<<endl;
    for(int i=1;i<=n;++i) printf("%d\n",c[i]-n);
    return 0;
}
View Code

 

posted @ 2020-03-09 15:07  逆天峰  阅读(229)  评论(0编辑  收藏  举报
作者:逆天峰
出处:https://www.cnblogs.com/gcfer//