zoukankan      html  css  js  c++  java
  • 洛谷$P2469 [SDOI2010]$ 星际竞速 网络流

    正解:网络流

    解题报告:

    传送门$QwQ$

    题目好长昂,,,大概概括下就说有$m$条单向边,$n$个点,每条边有一条边权,每个点有一个点权,然后问每个点都要到达一遍的最小代价是多少$QwQ$?

    发现有两个要求,一个是每个点恰好经过一次,一个是代价最小,不显然考虑最小费用最大流,,,?

    考虑拆点呗,先给源点和入点,出点和汇点分别连上流量为1费用为0的边,然后对于跳跃操作,就给源点和出点连上流量为1费用为$a_i$的边;对于航道$(x,y)$,就从$x$的入点连向$y$的出点,$over$

    昂正确性可以理解成类似于最小割的亚子,,,?

    就首先每个点要么是跳过去要么是通过路走过去.

    但是如果直接和$S$连路的代价$T$连跳的代价也布星,因为这样就不能保证每个点只被经过一次?就感性理解下,如果切断了两条边,但是这两条边的起点是一样的,这显然是布星的(因为每个点只能被经过一次鸭$QwQ$.

    所以就考虑拆点,这样就能保证每个点最多被经过一次了$QwQ$

    当然辣最后建图肯定和最小割还是有点儿差别的,,,毕竟一个费用流一个最大流显然还是不一样的鸭$QwQ$.

    但我的理解来说大致思想是差不多的所以我就用最小割解释了下$QwQ$

    实在不理解的自己画个图就好?$QwQ$

     

    #include<bits/stdc++.h>
    using namespace std;
    #define il inline
    #define gc getchar()
    #define t(i) edge[i].to
    #define w(i) edge[i].wei
    #define fy(i) edge[i].fy
    #define ri register int
    #define rc register char
    #define rb register bool
    #define rp(i,x,y) for(ri i=x;i<=y;++i)
    #define my(i,x,y) for(ri i=x;i>=y;--i)
    #define e(i,x) for(ri i=head[x];~i;i=edge[i].nxt)
    
    const int N=8000+10,M=150000+10;
    int n,m,ed_cnt=-1,head[N],dis[N],fr_ed[N],fr_nod[N],S,T,as;
    bool vis[N];
    struct ed{int to,nxt,wei,fy;}edge[M<<1];
    
    il int read()
    {
        rc ch=gc;ri x=0;rb y=1;
        while(ch!='-' && (ch>'9' || ch<'0'))ch=gc;
        if(ch=='-')ch=gc,y=0;
        while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc;
        return y?x:-x;
    }
    il void ad(ri x,ri y,ri z,ri p)
    {edge[++ed_cnt]=(ed){x,head[y],z,p};head[y]=ed_cnt;edge[++ed_cnt]=(ed){y,head[x],0,-p};head[x]=ed_cnt;}
    il bool spfa()
    {
        queue<int>Q;Q.push(S);memset(vis,0,sizeof(vis));memset(dis,63,sizeof(dis));vis[S]=1;dis[S]=0;
        while(!Q.empty())
        {
            ri nw=Q.front();Q.pop();vis[nw]=0;
            e(i,nw)
                if(w(i) && dis[t(i)]>dis[nw]+fy(i))
                {dis[t(i)]=dis[nw]+fy(i);fr_ed[t(i)]=i;fr_nod[t(i)]=nw;if(!vis[t(i)])Q.push(t(i)),vis[t(i)]=1;}
        }
        if(dis[T]==dis[T+1])return 0;
        ri flow=dis[T+1];
        for(ri i=T;i!=S;i=fr_nod[i])flow=min(flow,w(fr_ed[i]));
        for(ri i=T;i!=S;i=fr_nod[i])w(fr_ed[i])-=flow,w(fr_ed[i]^1)+=flow;
        as+=flow*dis[T];return 1;
    }
    
    
    int main()
    {
        //freopen("2469.in","r",stdin);freopen("2469.out","w",stdout);
        n=read();m=read();S=0;T=n<<1|1;memset(head,-1,sizeof(head));rp(i,1,n)ad(i,S,1,0),ad(T,i+n,1,0);
        rp(i,1,n)ad(i+n,S,1,read());rp(i,1,m){ri x=read(),y=read();if(x>y)swap(x,y);ad(y+n,x,1,read());}
        while(spfa());printf("%d
    ",as);
        return 0;
    }
    View Code

     

  • 相关阅读:
    cds.data:=dsp.data赋值有时会出现AV错误剖析
    iOS -- 十进制、十六进制字符串,byte,data等之间的转换
    iOS -- 原生NSStream实现socket
    CA认证原理以及实现(下)
    CA认证原理以及实现(上)
    android -- 存储byte
    iOS -- 字符串(NSString *)转uint8_t的两种方法
    Android -- AsyncTask 使用和缺陷
    Swift oc 混编
    Android -- native关键字
  • 原文地址:https://www.cnblogs.com/lqsukida/p/11371866.html
Copyright © 2011-2022 走看看