zoukankan      html  css  js  c++  java
  • 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的边,表示一个点只能走出去一次;

    n+i 向 T 连边权0,流量1的边,表示一个点只能到达一次;

    因为是DAG,所以不会有环,而且一定会有一个点瞬移开始;

    建图真妙啊!

    代码如下:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    int const xn=1605,xm=4e4+5,inf=0x3f3f3f3f;
    int n,m,S,T,hd[xn],ct=1,to[xm],nxt[xm],w[xm],c[xm],dis[xn],inc[xn],pre[xn];
    bool vis[xn];
    queue<int>q;
    int rd()
    {
      int ret=0,f=1; char ch=getchar();
      while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();}
      while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
      return f?ret:-ret;
    }
    void ade(int x,int y,int z,int f){to[++ct]=y; nxt[ct]=hd[x]; hd[x]=ct; w[ct]=z; c[ct]=f;}
    void add(int x,int y,int z,int f){ade(x,y,z,f); ade(y,x,-z,0);}
    bool bfs()
    {
      memset(dis,0x3f,sizeof dis);
      dis[S]=0; q.push(S); vis[S]=1; inc[S]=inf;//inc
      while(q.size())
        {
          int x=q.front(); q.pop(); vis[x]=0;
          for(int i=hd[x],u;i;i=nxt[i])
        if(dis[u=to[i]]>dis[x]+w[i]&&c[i])
          {
            dis[u]=dis[x]+w[i]; pre[u]=i;
            inc[u]=min(inc[x],c[i]);
            if(!vis[u])vis[u]=1,q.push(u);
          }
        }
      return dis[T]!=inf;
    }
    void upd()
    {
      int x=T;
      while(x!=S)
        {
          int i=pre[x];
          c[i]-=inc[T]; c[i^1]+=inc[T];
          x=to[i^1];
        }
    }
    int main()
    {
      n=rd(); m=rd(); S=0; T=(n<<1)+1;
      for(int i=1,x;i<=n;i++)
        x=rd(),add(S,i,0,1),add(S,n+i,x,1),add(n+i,T,0,1);
      for(int i=1,x,y,z;i<=m;i++)
        {
          x=rd(); y=rd(); z=rd();
          if(x>y)swap(x,y);
          add(x,n+y,z,1);//n+y
        }
      int ans=0;
      while(bfs())ans+=dis[T]*inc[T],upd();
      printf("%d
    ",ans);
      return 0;
    }
  • 相关阅读:
    计算机中丢失MSVCP110.dll
    应用程序无法正常启动0xc000007b
    查看80端口被占用
    重装系统后搭建php环境
    修改、设置root密码
    安装虚拟机时出现The Microsoft Runtime DLL
    linux网络配置
    Java拾遗
    哈希中的那些序问题
    笔记本电脑安装jupyterthemes
  • 原文地址:https://www.cnblogs.com/Zinn/p/10134831.html
Copyright © 2011-2022 走看看