zoukankan      html  css  js  c++  java
  • BZOJ 3876 支线剧情 有源汇有上下界最小费用可行流

    题意:

      给定一张拓扑图,每条边有边权,每次只能从第一个点出发沿着拓扑图走一条路径,求遍历所有边所需要的最小边权和

    分析:

      这道题乍一看,可能会想到什么最小链覆盖之类的,但是仔细一想,会发现不行,一是因为每条边都会有贡献,而不是每条链,二是因为边有特定的边权,所以这道题只能用建图复杂一些的网络流来解决。

      其实也挺简单的。都不用建超级源点,直接从1号点当源点就行,每条边费用为边权,容量下界为1,上界无穷大。

      然后建图跑最小费用可行流就可以了。

    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;int S,T,tot=0;
     3 const int N=505,M=500005,inf=0x3f3f3f3f;
     4 struct node{int y,f,c,nxt;}e[M];int c=1,t[N];
     5 int h[N],q[M],d[N],n,m,s,pre[N];bool vis[N];
     6 void add(int x,int y,int z,int w){
     7     e[++c]=(node){y,z,w,h[x]};h[x]=c;
     8     e[++c]=(node){x,0,-w,h[y]};h[y]=c;
     9 } bool spfa(){
    10     for(int i=0;i<=T;i++) d[i]=inf;
    11     int l=1,r=0;q[++r]=S;vis[S]=1;d[S]=0;
    12     while(l<=r){ 
    13         int x=q[l++];vis[x]=0;
    14         for(int i=h[x],y;i;i=e[i].nxt)
    15         if(d[y=e[i].y]>d[x]+e[i].c&&e[i].f){
    16             d[y]=d[x]+e[i].c;pre[y]=i;
    17             if(!vis[y]) q[++r]=y,vis[y]=1;}
    18     } return (d[T]!=inf);
    19 } void aug(){ int x=inf;
    20     for(int i=pre[T];i;i=pre[e[i^1].y]) 
    21     x=min(x,e[i].f);
    22     for(int i=pre[T];i;i=pre[e[i^1].y])
    23     tot+=x*e[i].c,e[i].f-=x,e[i^1].f+=x;
    24 } int main(){
    25     scanf("%d",&n);S=1,T=n+1;
    26     for(int i=1,k,y,v;i<=n;i++){
    27         scanf("%d",&k);while(k--)
    28         scanf("%d%d",&y,&v),
    29         add(i,y,inf,v),t[y]++,t[i]--,tot+=v;
    30     } for(int i=1;i<=n;i++)
    31     if(t[i]>0) add(S,i,t[i],0);
    32     else if(t[i]<0) add(i,T,-t[i],0);
    33     while(spfa()) aug();
    34     printf("%d
    ",tot);return 0;
    35 }
    有源汇有上下界最小费用可行流
  • 相关阅读:
    saltstack配置管理之YAML(二)
    自动化运维之saltstack 简单用法(一)
    异常处理,枚举,泛型
    面向对象二
    面向对象
    python面向对象
    方法(函数),内存空间,数组
    for循环,while循环,do while循环
    if判断,switch语句
    运算符
  • 原文地址:https://www.cnblogs.com/Alan-Luo/p/10256872.html
Copyright © 2011-2022 走看看