• [codeforces 852 D] Exploration Plan 解题报告 (二分+最大匹配)


    题目链接:http://codeforces.com/problemset/problem/852/D

    题目大意:

    有V个点,N个队伍,E条边,经过每条边有个时间,告诉你初始N个队伍的位置,求至少有K个队伍在不同的点的最短时间

    题解:

    我们二分答案时间,显然具有单调性。先floyd预处理两点之间的最短路,二分答案后把每个人和他可以走到的点连起来,跑一次最大匹配。若最大匹配数大于等于k,说明当前答案小了,否则大了

    (每个匹配相等于一个人和他最终去的位置)

    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cstdio>
    using namespace std;
    
    const int N=600+15;
    const int inf=1e9+7;
    const int Inf=1731311;
    int v,e,n,k;
    int pos[N],d[N][N],mp[N][N],match[N],vis[N];
    inline int read()
    {
        char ch=getchar();
        int s=0,f=1;
        while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
        while (ch>='0'&&ch<='9') {s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
        return s*f;
    }
    void floyd()
    {
        for (int k=1;k<=v;k++)
            for (int i=1;i<=v;i++)    
                for (int j=1;j<=v;j++) d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
    }
    bool dfs(int x)
    {
        for (int i=1;i<=v;i++)
        {
            if (vis[i]||!mp[x][i]) continue;
            vis[i]=1;
            if (match[i]==-1||dfs(match[i]))
            {
                match[i]=x;
                return true;        
            }
        }
        return false;
    }
    int check(int l)
    {
        memset(match,-1,sizeof(match));
        for (int i=1;i<=n;i++)    
            for (int j=1;j<=v;j++)
             mp[i][j]=(d[pos[i]][j]<=l);
        int ans=0;
        for (int i=1;i<=n;i++)
        {
            memset(vis,0,sizeof(vis));
            if (dfs(i)) ans++;
        }
        return ans;    
    }
    int main()
    {
        v=read();e=read();n=read();k=read();
        for (int i=1;i<=v;i++)    
            for (int j=1;j<=v;j++) if (i!=j) d[i][j]=inf;
        for (int i=1;i<=n;i++) pos[i]=read();
        for (int i=1,u,v,w;i<=e;i++)
        {
            u=read();v=read();w=read();
            d[u][v]=d[v][u]=min(d[u][v],w);
        }
        floyd();
        int l=0,r=Inf,ans=Inf;
        while (l<r)
        {
            int mid=l+r>>1;
            if (check(mid)>=k) r=mid,ans=min(ans,r);
            else l=mid+1;
        }
        if (ans==Inf) puts("-1");
        else printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    ASP.NET Web API 2 框架揭秘
    跨境之二 对外服务接口接收订单数据(跨境通关申报系统)
    关于程序员的59条搞笑但却真实无比的编程语录
    linux终端常用快捷键
    [ json editor] 如何在网页中使用Json editor 插件
    【简洁之美】裴波那切数列生成器 python
    python 实现树结构的打印
    windows python文件拷贝到linux上执行问题
    python 中变量的命名方法
    <select> 标签使用
  • 原文地址:https://www.cnblogs.com/xxzh/p/9762720.html
Copyright © 2020-2023  润新知