bzoj千题计划159:bzoj2055: 80人环游世界(上下界费用流)

Posted 日拱一卒 功不唐捐

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj千题计划159: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=1; decc=(n<<1|1)+1; T=decc+1;
    int x;
    for(int i=1;i<=n;++i) 
    {
        read(x);
        if(!x) continue;
        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);
        }
    }
    for(int i=1;i<=n;++i) add(1,i<<1,m,0);
    add(S,1,m,0);
    add(decc,T,m,0);
    add(decc,src,m,0);
    zkw();
}
View Code

 

技术分享图片
#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==decc)
    {
        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[decc]) 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<=decc;++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=1; decc=(n<<1|1)+1; 
    int x;
    for(int i=1;i<=n;++i) 
    {
        read(x);
        if(!x) continue;
        add(i<<1,decc,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);
        }
    }
    for(int i=1;i<=n;++i) add(1,i<<1,m,0);
    add(S,1,m,0);
    zkw();
}
View Code

 

以上是关于bzoj千题计划159:bzoj2055: 80人环游世界(上下界费用流)的主要内容,如果未能解决你的问题,请参考以下文章

bzoj2055 80人环游世界

[bzoj2055] 80人环游世界

bzoj2055: 80人环游世界(可行流)

bzoj 2055 80人环游世界

bzoj千题计划263:bzoj4870: [六省联考2017]组合数问题

bzoj千题计划130:bzoj1305: [CQOI2009]dance跳舞