zoukankan      html  css  js  c++  java
  • bzoj2055: 80人环游世界(有源汇上下界可行最小费用流)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2055

    某个国家必须经过vi次,

    可以转化为上下界都为vi的边

    对这张图做有源汇上下界可行最小费用流

     按无源汇上下界可行流建好图,跑超级源点到超级汇点的最小费用最大流即可

     
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
     
    using namespace std;
     
    #define N 205
    #define M 10500
     
    const int inf=1e9;
     
    int src,decc;
    int S,T;
     
    int tot=1;
    int front[N],to[M<<1],nxt[M<<1],cap[M<<1],val[M<<1],from[M<<1];
     
    int cost;
     
    int dis[N];
    bool vis[N];
     
    void read(int &x)
    {
        x=0;  int f=1; char c=getchar();
        while(!isdigit(c)) { if(c=='-') f=-1; c=getchar(); }
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
        x*=f;
    }
     
    void add(int u,int v,int w,int f)
    {
        to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; from[tot]=u; cap[tot]=w; val[tot]=f;
        to[++tot]=u; nxt[tot]=front[v]; front[v]=tot; from[tot]=v; cap[tot]=0; val[tot]=-f; 
    }
     
    int agument(int now,int flow)
    {
        vis[now]=true;
        if(now==T)
        {
            cost-=dis[S]*flow;
            return flow;
        }
        int delta;
        for(int i=front[now];i;i=nxt[i])
        {
            if(cap[i] && !vis[to[i]] && dis[to[i]]==dis[now]+val[i])
            {
                delta=agument(to[i],min(flow,cap[i]));
                if(delta)
                {
                    cap[i]-=delta;
                    cap[i^1]+=delta;
                    return delta;
                }
            }
        }
        return 0;
    }
     
    bool retreat()
    {
        if(vis[T]) return true;
        int mi=inf;
        for(int i=2;i<=tot;++i)
            if(cap[i] && vis[from[i]] && !vis[to[i]])
                mi=min(mi,dis[from[i]]+val[i]-dis[to[i]]);
        if(mi==inf) return false;
        for(int i=0;i<=T;++i)
            if(vis[i]) dis[i]-=mi;
        return true; 
    }
     
    void zkw()
    {
        do
        {
            memset(vis,false,sizeof(vis));
            agument(S,inf);
        }while(retreat());
        cout<<cost;
    }
     
    int main()
    {
        int n,m;
        read(n); read(m);
        src=0; decc=(n<<1|1)+1;
        int ss=1; 
        S=decc+1; T=S+1;
        add(src,T,m,0);
        add(S,ss,m,0);
        int x;
        for(int i=1;i<=n;++i) 
        {
            read(x);
            add(ss,i<<1,m,0);
            add(i<<1|1,decc,m,0);
            add(i<<1,T,x,0);
            add(S,i<<1|1,x,0);
        }
        int k;
        for(int i=1;i<n;++i)
        {
            for(int j=i+1;j<=n;++j) 
            {
                read(x);
                if(x==-1) continue;
                add(i<<1|1,j<<1,m,x);
            }
        }
        add(decc,src,m,0);
        zkw();
    } 
  • 相关阅读:
    从自然数到有理数
    付费版乐影音下载器使用方法
    Avtiviti之流程变量
    activity(工作流)初步学习记录
    IntelliJ IDEA安装Activiti插件并使用
    golang 性能测试
    Golang性能测试工具PProf应用详解
    java连接ZK的基本操作
    会员体系、积分、等级
    Flink基本概念
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8087597.html
Copyright © 2011-2022 走看看