zoukankan      html  css  js  c++  java
  • 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
    ",c[i]-n);
        return 0;
    }
    View Code
  • 相关阅读:
    HDU4366 Successor 线段树+预处理
    POJ2823 Sliding Window 单调队列
    HDU寻找最大值 递推求连续区间
    UVA846 Steps 二分查找
    HDU3415 Max Sum of MaxKsubsequence 单调队列
    HDU时间挑战 树状数组
    UVA10168 Summation of Four Primes 哥德巴赫猜想
    UESTC我要长高 DP优化
    HDUChess 递推
    HDU4362 Dragon Ball DP+优化
  • 原文地址:https://www.cnblogs.com/gcfer/p/12448834.html
Copyright © 2011-2022 走看看