【Bzoj1927】星际竞速(费用流)

Description

题意:给定n个点m条边的无向图,只能从编号小的到编号大的,且要求经过所有点刚好一次,而且可以从任意点瞬移到i号点并花费代价Ai,求最小代价。

n<=800,m<=15000

Solution

Code

#include <cstdio>
#include <algorithm>
#include <queue>
#define N 2010
#define Inf 0x7fffffff
using namespace std;

struct info{int to,nex,f,c;}e[N*100];
int n,m,T,S,tot,nodes,head[N],Ans;
int dis[N],fr[N];
bool vis[N];

inline void Link(int u,int v,int f,int c){
    e[++tot].to=v;e[tot].nex=head[u];head[u]=tot;e[tot].f=f;e[tot].c=c;
    e[++tot].to=u;e[tot].nex=head[v];head[v]=tot;e[tot].f=0;e[tot].c=-c;
}

inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

inline void Init(){
    n=read(),m=read();
    S=0,T=n*2+1;tot=1;
    for(int i=1;i<=n;++i){
        int t=read();
        Link(S,i,1,0);
        Link(i+n,T,1,0);
        Link(S,i+n,1,t);
    }
    while(m--){
        int u=read(),v=read(),w=read();
        if(u>v) swap(u,v);
        Link(u,v+n,1,w);
    }
}

queue<int> q;
bool spfa(){
    for(int i=0;i<=T;++i)dis[i]=Inf;
    while(!q.empty()) q.pop();
    dis[0]=0,q.push(0),vis[0]=1;

    while(!q.empty()){
        int u=q.front();q.pop();
        //vis[u]=0;
        for(int i=head[u];i;i=e[i].nex){
            int v=e[i].to;
            if(e[i].f&&dis[v]>dis[u]+e[i].c){
                dis[v]=dis[u]+e[i].c;
                fr[v]=i;
                if(!vis[v]){vis[v]=1;q.push(v);}
            }
        }
        vis[u]=0;
    }
    if(dis[T]==Inf) return 0;
    return 1;
}

void mcf(){
    int x=Inf;
    for(int i=fr[T];i;i=fr[e[i^1].to])
        x=min(x,e[i].f);
    for(int i=fr[T];i;i=fr[e[i^1].to]){
        Ans+=x*e[i].c;
        e[i].f-=x;
        e[i^1].f+=x;
    }
}

int main(){
    Init();
    while(spfa()) mcf();
    printf("%d\n",Ans);
    return 0;
}

原文地址:https://www.cnblogs.com/void-f/p/8492427.html

时间: 2024-10-09 12:24:19

【Bzoj1927】星际竞速(费用流)的相关文章

BZOJ 1927: [Sdoi2010]星际竞速 费用流

1927: [Sdoi2010]星际竞速 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=1927 Description 10 年一度的银河系赛车大赛又要开始了.作为全银河最盛大的活动之一, 夺得这个项目的冠军无疑是很多人的梦想,来自杰森座 α星的悠悠也是其中之一. 赛车大赛的赛场由 N 颗行星和M条双向星际航路构成,其中每颗行星都有 一个不同的引力值.大赛要

BZOJ 1927 SDOI 2010 星际竞速 费用流

题目大意:宇宙空间中进行了一次竞速大赛.有两种飞行方式,第一种是通过正常的道路,但是只能从标号小的飞到标号大的地方:第二种是直接过去,但是需要花费固定的时间.问正好遍历一次所有的点最少需要的多少时间. 思路:费用流.把每个点拆点,S到每个点的起点连费用0的边,向每个终点连费用为固定费用的边,图中原有的边从一个的起点连到另一个点的终点.然后每个点的终点向T连边.跑最小费用最大流就是最后的答案. CODE: #include <queue> #include <cstdio> #inc

BZOJ 1927 星际竞速(费用流)

考虑费用流,题目要求走n个点都走完且恰好一次,显然流量的限制为n. 建立源点s和汇点t,并把每个星球拆成两个点i和i',分别表示已到达该点和经过该点. 对于能力爆发,建边(s,i',1,w). 对应高速航行,建边(s,i,1,0), (i,j',1,w). 因为每个点必须走一次且只能走一次.建边(i',t,1,0). 其实就是类似最小路径覆盖的建图方法. # include <cstdio> # include <cstring> # include <cstdlib>

【bzoj1927】[Sdoi2010]星际竞速 有上下界费用流

原文地址:http://www.cnblogs.com/GXZlegend/p/6832464.html 题目描述 10年一度的银河系赛车大赛又要开始了.作为全银河最盛大的活动之一,夺得这个项目的冠军无疑是很多人的梦想,来自杰森座α星的悠悠也是其中之一.赛车大赛的赛场由N颗行星和M条双向星际航路构成,其中每颗行星都有一个不同的引力值.大赛要求车手们从一颗与这N颗行星之间没有任何航路的天体出发,访问这N颗行星每颗恰好一次,首先完成这一目标的人获得胜利.由于赛制非常开放,很多人驾驶着千奇百怪的自制赛

BZOJ 1927 星际竞速(最小费用最大流)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1927 题意:一个图,n个点.对于给出的每条边 u,v,w,表示u和v中编号小的那个到编号大的那个的时间为w.另外有n个值Ai,表示从任何一个点到达i点的时间为Ai.初始时你在n个点之外的一个 点上,我们称其为初始点B.要求从B出发,遍历n个点每个点一次,求最小时间.显然开始你只能使用Ai从B到达n个点中的某个点,因为B到n个点中没有其 他的边. 思路:因为最后停在了某个点上,那么从B出

bzoj 1927 [Sdoi2010]星际竞速(最小费用最大流)

1927: [Sdoi2010]星际竞速 Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 1576  Solved: 954[Submit][Status][Discuss] Description 10 年一度的银河系赛车大赛又要开始了.作为全银河最盛大的活动之一, 夺得这个项目的冠军无疑是很多人的梦想,来自杰森座 α星的悠悠也是其中之一. 赛车大赛的赛场由 N 颗行星和M条双向星际航路构成,其中每颗行星都有 一个不同的引力值.大赛要求车手们从一

BZOJ 1927: [Sdoi2010]星际竞速(最小费用最大流)

拆点,费用流... ----------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<queue> #define rep( i, n ) for( int i = 0; i < n; +

【费用流】BZOJ1927-[Sdoi2010]星际竞速

[题目大意] 有一些点,它们之间存在一些有向边(由编号小的到编号大的),从一点到另一点消耗时间为边长.也可以消耗Ti时间直接抵达任意一个点.问所有点都走一遍最少需要多少时间? [思路] ①将每个点i拆为i和i’. ②由S向i连(cap=1,cost=0)的边.由i'向T连(1,0)的边,表示抵达过该点. ③由S向i'连(1,Ti)的边,表示直接从某点跳转到i点. ④根据有向边[i,j]连(i,j')的边. 为什么这样是正确的?由于我们只关心每个点都被抵达过而不关心路径.费用流的前提是最大流,我们

bzoj1927: [Sdoi2010]星际竞速

跟上一题几乎一样... #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<queue> using namespace std; #define rep(i,n) for(int i=1;i<=n;i++) #define clr(x,c) memset(x,c,sizeof(x)) #define op() clr(head

P4553 80人环游世界 上下界费用流

题意: 有1-n个城市  有m个人去旅游  每个人只能从编号小的城市到编号大的城市  花费费用为COSTij   一开始每个人可以从任意一个城市开始旅行   且每个城市恰好有Vi个人经过(一开始也算经过) 问最小花费 显然用有上下界的费用流非常好理解  每个点进行拆点 两点之间连上界和下界都为Vi 表示正好通过Vi人      然后经典连图即可 再控制一下人数m  跑模板 (正面建图) #include<bits/stdc++.h> using namespace std; //input b