bzoj 1927 [Sdoi2010]星际竞速【最小费用最大流】

果然还是不会建图…

设\( i \)到\( j \)有通路,代价为\( w[i][j] \),瞬移到i代价为\( a[i] \),瞬移到i代价为\( a[j] \),逗号前是流量。

因为每个点只能经过一次,所以流量限制为1,注意到从s开始很难保证出发点不同,所以但是又有联通条件,所以考虑每个扩展过的点(实际不用考虑反正早晚要扩展到)只向外扩展一个点,也就是每次只选两个联通的点(包括瞬移可达)

拆点的作用是加上费用,\( s \)到所有\( i \)连流量1费用0的边,所有\(i \)向t连流量1费用0的边,\( i \)到\( i+n \)连流量1费用\( a[i] \)的边,对于可以相互到达的\( i、j \),连流量为1费用为\( v[i][j] \)的边(\( u<v \))

是不是有点像最小路径覆盖?

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
const int N=5005,inf=1e9;
int n,m,a[N],s,t,ans,fr[N],dis[N],h[N],cnt=1;
bool v[N];
struct qwe
{
    int ne,no,to,va,c;
}e[N*100];
int read()
{
    int r=0,f=1;
    char p=getchar();
    while(p>‘9‘||p<‘0‘)
    {
        if(p==‘-‘)
            f=-1;
        p=getchar();
    }
    while(p>=‘0‘&&p<=‘9‘)
    {
        r=r*10+p-48;
        p=getchar();
    }
    return r*f;
}
void add(int u,int v,int w,int c)
{
    cnt++;
    e[cnt].ne=h[u];
    e[cnt].no=u;
    e[cnt].to=v;
    e[cnt].va=w;
    e[cnt].c=c;
    h[u]=cnt;
}
void ins(int u,int v,int w,int c)
{
    add(u,v,w,c);
    add(v,u,0,-c);
}
bool spfa()
{
    queue<int>q;
    for(int i=s;i<=t;i++)
        dis[i]=inf;
    dis[s]=0;
    v[s]=1;
    q.push(s);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        v[u]=0;
        for(int i=h[u];i;i=e[i].ne)
            if(e[i].va>0&&dis[e[i].to]>dis[u]+e[i].c)
            {
                dis[e[i].to]=dis[u]+e[i].c;
                fr[e[i].to]=i;
                if(!v[e[i].to])
                {
                    v[e[i].to]=1;
                    q.push(e[i].to);
                }
            }
    }
    return dis[t]!=inf;
}
void mcf()
{
    int x=inf;
    for(int i=fr[t];i;i=fr[e[i].no])
        x=min(x,e[i].va);
    for(int i=fr[t];i;i=fr[e[i].no])
    {
        ans+=x*e[i].c;
        e[i].va-=x;
        e[i^1].va+=x;
    }
}
int main()
{
    n=read(),m=read();
    t=2*n+1;
    for(int i=1;i<=n;i++)
    {
        a[i]=read();
        ins(s,i,1,0);
        ins(i+n,t,1,0);
        ins(s,i+n,1,a[i]);
    }
    for(int i=1;i<=m;i++)
    {
        int u=read(),v=read(),w=read();
        if(u>v)
            swap(u,v);
        ins(u,v+n,1,w);
    }
    while(spfa())
        mcf();
    printf("%d\n",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/lokiii/p/8185495.html

时间: 2024-08-28 16:56:30

bzoj 1927 [Sdoi2010]星际竞速【最小费用最大流】的相关文章

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

拆点,费用流... ----------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<queue> #define rep( i, n ) for( int i = 0; i < 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]星际竞速 费用流

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 星际竞速 —— 最小费用最大流

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1927 首先注意到这是个DAG: 考虑每个点从哪里来,可以是瞬移来的,也可以是从某个点走过来的,而从每个点走出去只能用一次: 所以拆点,i 表示从这个点走出去,n+i 表示来到这个点: 建图: 1.瞬移:S 向 n+i 连边权 a[i],流量1的边 2.走过来:如果 i 能走到 j,那么 i 向 n+j 连边权 w,流量1的边 然后 S 向 i 连边权0,流量1的边,表示一个点只能走出去一次

bzoj 1927: [Sdoi2010]星际竞速

1 #include<cstdio> 2 #include<iostream> 3 #define M 1605 4 #define S 3000005 5 using namespace std; 6 int q[S],f[M],n,m,ans,a[M],head[M],next[S],u[S],v[S],c[S],fr[S],cnt=1,d[M],fro[M],T; 7 void jia(int a1,int a2,int a3,int a4) 8 { 9 cnt++; 10

1927: [Sdoi2010]星际竞速

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

BZOJ 1449 球队收益(最小费用最大流)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1449 题意: 思路:首先,我们假设后面的M场比赛两方都是输的,即初始时的lose[i]再加上i参加的场次.这样,后面对于i,每赢一场的收益增加值为: 之后win[i]++,lose[i]--.至此,我们得到建图的方法: (1)源点到每场比赛连流量1,费用0: (2)每场比赛向双方连流量1,费用0: (3)每个人到汇点连x条边(x为该人在M场比赛中出现的次数),流量1,费用为上面计算出的

BZOJ 1061 志愿者招募(最小费用最大流)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1061 题意:申奥成功后,布布经过不懈努力,终于 成为奥组委下属公司人力资源部门的主管.布布刚上任就遇到了一个难题:为即将启动的奥运新项目招募一批短期志愿者.经过估算,这个项目需要N 天才能完成,其中第i 天至少需要Ai 个人. 布布通过了解得知,一共有M 类志愿者可以招募.其中第i 类可以从第Si 天工作到第Ti 天,招募费用是每人Ci 元.新官上任三把火,为了出色地完成自己的工作,布