zoukankan      html  css  js  c++  java
  • luoguP2526_[SHOI2001]小狗散步_二分图匹配

    luoguP2526_[SHOI2001]小狗散步_二分图匹配

    题意:

    Grant喜欢带着他的小狗Pandog散步。Grant以一定的速度沿着固定路线走,该路线可能自交。Pandog喜欢游览沿途的景点,不过会在给定的N个点和主人相遇。小狗和主人同时从(X1,Y1)点出发,并同时在(Xn,Yn)点汇合。小狗的速度最快是Grant的两倍。当主人从一个点以直线走向另一个点时,Pandog跑向一个它感兴趣的景点。Pandog每次与主人相遇之前最多只去一个景点。

    分析:

    我们可以把人每次走的一条路径当作点,显然狗只能从出发点走到符合条件的部分点,把这两个点连边,表示狗要么跟人走,要么选择一条能走的路走。

    求二分图最大匹配即可

    代码:

    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <math.h>
    #include <queue>
    using namespace std;
    #define N 600
    #define du double
    #define S (n+m+1)
    #define T (n+m+2)
    #define inf 100000000
    int head[N],to[N*N<<1],nxt[N*N<<1],flow[N*N<<1],cnt=1,n,m,dep[N];
    inline void add(int u,int v,int f){
        to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;flow[cnt]=f;
        to[++cnt]=u;nxt[cnt]=head[v];head[v]=cnt;flow[cnt]=0;
    }
    struct P{
        int x,y;
    }a[N],b[N];
    du dis(P u,P v){
        return sqrt((u.x-v.x)*(u.x-v.x)+(u.y-v.y)*(u.y-v.y));
    }
    bool bfs(){
        queue <int> q;
        q.push(S);memset(dep,0,sizeof(dep));
        dep[S]=1;
        while(!q.empty()){
            int x=q.front();q.pop();
            for(int i=head[x];i;i=nxt[i]){
                if(!dep[to[i]]&&flow[i]){
                    dep[to[i]]=dep[x]+1;
                    if(to[i]==T)return 1;
                    q.push(to[i]);
                }
            }
        }
        return 0;
    }
    int dfs(int x,int mf){
        if(x==T)return mf;
        int nf=0;
        for(int i=head[x];i;i=nxt[i]){
            if(dep[to[i]]==dep[x]+1&&flow[i]){
                int tmp=dfs(to[i],min(flow[i],mf-nf));
                nf+=tmp;
                flow[i]-=tmp;
                flow[i^1]+=tmp;
                if(nf==mf)break;    
            }
        }
        dep[x]=0;return nf;
    }
    void dinic(){
        int ans=0,f;
        while(bfs())while(f=dfs(S,inf))ans+=f;
        printf("%d
    ",ans+n);
        for(int i=1;i<n;i++){
            printf("%d %d ",a[i].x,a[i].y);
            for(int j=head[i];j;j=nxt[j]){
                if(to[j]!=S&&flow[j]==0){
                    printf("%d %d ",b[to[j]-n+1].x,b[to[j]-n+1].y);    
                }
            }
        }
        printf("%d %d",a[n].x,a[n].y);
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d%d",&a[i].x,&a[i].y);
            if(i^n)add(S,i,1);
        }
        for(int i=1;i<=m;i++){
            scanf("%d%d",&b[i].x,&b[i].y);    
            add(i+n-1,T,1);
        }
        for(int i=1;i<n;i++){
            for(int j=1;j<=m;j++){
                if(dis(a[i],a[i+1])>=(dis(a[i],b[j])+dis(a[i+1],b[j]))/2){
                    add(i,j+n-1,1);    
                }
            }
        }
        dinic();
    }
    
  • 相关阅读:
    括号
    vue 框架原理
    Angular 1.x 框架原理
    ES5的数组方法
    js 对象细节
    《高性能网站建设进阶指南》笔记
    vue 运行时 + 编译器 vs. 只包含运行时
    vue-loader 细节
    vue 错误处理
    移动web touch事件
  • 原文地址:https://www.cnblogs.com/suika/p/8456979.html
Copyright © 2011-2022 走看看