zoukankan      html  css  js  c++  java
  • BZOJ 1834网络扩容题解

    一道不算太难的题目

    但是真的很恶心

    显然,对于第一问,我们直接无脑打模板就好了

    第二问也不是很难,我们将每条边再连一条容量为inf,费用为w的边

     但是流量只要小于第一问的答案加k就行了

    所以我们增加一个点为第二问的汇点,将n与它连接一条容量为ans+k,费用为0的边

    跑费用流就好了

    但是!!!!!!!

    这样作只有40分,为什么呢。

    因为虽然数据范围说n<=1000但给的点编号有大于1000的点。。。。。

    我们只要将点数视为5000就可以过来了

    真的恶心。。。。

    不过在考场上还是建议用离散化,毕竟你不知道点数编号的范围

    想问一问当初省选时有多少人被这个给坑了。。

    # include<iostream>
    # include<cstdio>
    # include<cmath>
    # include<algorithm>
    # include<cstring>
    # include<queue>
    using namespace std;
    const int mn = 5005;
    const int inf = 0xfffffff;
    struct edge{
    int to,next,flow,cup,cost;
    edge(){to=flow=cup=cost=0,next=-1;}
    };
    edge e[mn*10];
    int head[mn],edge_max=-1;
    void add(int x,int y,int k,double c)
    {
        e[++edge_max].to=y;
        e[edge_max].next=head[x];
        e[edge_max].flow=e[edge_max].cup=k;
        e[edge_max].cost=c;
        head[x]=edge_max;
    }
    int n,m,k;
    int ans1,ans2;
    int deep[mn];
    int cur[mn];
    queue<int> q;
    bool bfs(int x,int y)
    {
       memset(deep,0,sizeof(deep));
       q.push(x);
       deep[x]=1;
       while(!q.empty())
       {
           int u=q.front();
           q.pop();
           for(int i=head[u];i!=-1;i=e[i].next)
           {
               if(deep[e[i].to]==0 && e[i].flow>0 )
               {
                   deep[e[i].to]=deep[u]+1;
                   q.push(e[i].to);
               }
           }
       }
       if(deep[y]==0)
        return false;
       else return true;
    }
    int dfs(int x,int dist,int y)
    {
        if(x==y)
            return dist;
        for(int &i=cur[x];i!=-1;i=e[i].next)
        {
           if(deep[e[i].to]==deep[x]+1 && e[i].flow!=0)
           {
              int di=dfs(e[i].to,min(dist,e[i].flow),y);
              if(di>0)
              {
                  e[i].flow-=di;
                  e[i^1].flow+=di;
                  return di;
              }
           }
        }
        return 0;
    }
    void dinic(int x,int y)
    {
        while(bfs(x,y))
        {
            for(int i=1;i<=n;i++)
              cur[i]=head[i];
            while(int k=dfs(x,inf,y))
                ans1+=k;
        }
    }
    int dis[mn];
    int pe[mn],pv[mn];
    bool vis[mn];
    bool spfa(int x,int y)
    {
       memset(vis,0,sizeof(vis));
       for(int i=1;i<=n+1;i++)
        dis[i]=inf;
       dis[x]=0;
       vis[x]=1;
       q.push(x);
       while(!q.empty())
       {
           int u=q.front();
           q.pop();
           vis[u]=0;
           for(int i=head[u];i!=-1;i=e[i].next)
           {
               if(dis[u]+e[i].cost<dis[e[i].to] && e[i].flow>0)
               {
                     dis[e[i].to]=e[i].cost+dis[u];
                     pe[e[i].to]=i;
                     pv[e[i].to]=u;
                     if(!vis[e[i].to])
                     {
                         q.push(e[i].to);
                         vis[e[i].to]=1;
                     }
               }
           }
       }
       if(dis[y]!=inf)
        return true;
       else return false;
    }
    void max_flow(int x,int y)
    {
       while(spfa(x,y))
       {
          int mflow=inf;
          for(int i=y;i!=x;i=pv[i])
          {
              mflow=min(mflow,e[pe[i]].flow);
          }
          ans2+=dis[y]*mflow;
          for(int i=y;i!=x;i=pv[i])
          {
              e[pe[i]].flow-=mflow;
              e[pe[i]^1].flow+=mflow;
          }
       }
    }
    int a1[mn],a2[mn],a3[mn],a4[mn];
    void pre()
    {
        memset(head,-1,sizeof(head));
        memset(e,-1,sizeof(e));
        for(int i=1;i<=m;i++)
        {
            add(a1[i],a2[i],a3[i],0);
            add(a2[i],a1[i],0,0);
            add(a1[i],a2[i],inf,a4[i]);
            add(a2[i],a1[i],0,-a4[i]);
        }
    }
    int main()
    {
       int x,y,c,w;
       memset(head,-1,sizeof(head));
       scanf("%d%d%d",&n,&m,&k);
       for(int i=1;i<=m;i++)
       {
           scanf("%d%d%d%d",&a1[i],&a2[i],&a3[i],&a4[i]);
           add(a1[i],a2[i],a3[i],0);
           add(a2[i],a1[i],0,0);
       }
       dinic(1,n);
       pre();
       add(n,n+1,ans1+k,0);
       add(n+1,n,0,0);
       max_flow(1,n+1);
       printf("%d %d",ans1,ans2);
       return 0;
    }
  • 相关阅读:
    基数排序
    计数排序和桶排序
    部署Java Web项目到云服务器的步骤全解析
    IP地址0.0.0.0/0是什么意思
    Tomcat在阿里云Centos7上正常启动,但浏览器无法访问的解决方法
    eclipse光标怎么返回上一次浏览的位置
    IDEA设置方法自动显示参数提示
    socket通信模型、socket中的accept()阻塞与read()阻塞
    Ubuntu18.04 下修改 root密码
    Ubuntu18.04 安装 VMwareTools
  • 原文地址:https://www.cnblogs.com/logeadd/p/8759238.html
Copyright © 2011-2022 走看看