zoukankan      html  css  js  c++  java
  • 洛谷4400 BlueMary的旅行(分层图+最大流)

    qwq
    首先,我们观察到题目中提到的每天只能乘坐一次航班的限制,很容易想到建分层图,也就是通过枚举天数,然后每天加入一层新的点。
    (然而我一开始想的却是erf)

    考虑从小到大枚举天数,然后每次新建一层。

    首先我们先让(S->第0层的对应的起始节点),流量为初始人数的边

    然后相邻两层之间,若存在航班,则两个之间连流量为次数的边。
    对应节点之间连(inf)的边,表示可以待在原地。

    然后每一层的结束节点,都向T连边,表示每一天都可以有人到达终止节点。

    然后直接跑最大流,假设初始人数是(k),每次让(k-=maxflow)

    直到(k=0),输出对应的天数即可

    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    #define mk make_pair
    #define pb push_back
    #define ll long long
    
    using namespace std;
    
    inline int read()
    {
      int x=0,f=1;char ch=getchar();
      while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
      while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
      return x*f;
    }
    
    const int maxn = 10010;
    const int maxm = 2e6+1e2;
    const int inf = 1e9;
    
    int point[maxn],nxt[maxm],to[maxm],val[maxm];
    int cnt=1,n,m;
    int h[maxn];
    
    void addedge(int x,int y,int w)
    {
        nxt[++cnt]=point[x];
        to[cnt]=y;
        val[cnt]=w;
        point[x]=cnt;
    }
    
    void insert(int x,int y,int w)
    {
        addedge(x,y,w);
        addedge(y,x,0);
    }
    
    int s,t;
    queue<int> q;
    
    bool bfs(int s)
    {
        memset(h,-1,sizeof(h));
        h[s]=0;
        q.push(s);
        while (!q.empty())
        {
            int x= q.front();
            q.pop();
            for (int i=point[x];i;i=nxt[i])
            {
                int p=to[i];
                if (h[p]==-1 && val[i]>0)
                {
                    h[p]=h[x]+1;
                    q.push(p);
                }
            }
        }
        if (h[t]==-1) return false;
        return true;    
    }
    
    int dfs(int x,int low)
    {
        if (x==t || low==0) return low;
        int totflow=0;
        for (int i=point[x];i;i=nxt[i])
        {
            int p = to[i];
            if(h[p]==h[x]+1 && val[i]>0)
            {
                int tmp = dfs(p,min(low,val[i]));
                val[i]-=tmp;
                val[i^1]+=tmp;
                low-=tmp;
                totflow+=tmp;
                if(low==0) return totflow;
            }
        }
        if(low>0) h[x]=-1;
        return totflow;
    } 
     
    int dinic()
    {
        int ans=0;
        while (bfs(s))
        {
            ans=ans+dfs(s,inf);
        }
        return ans;
    }
    
    int x[maxm],y[maxm],w[maxm];
    int k;
    
    int main()
    {
      s=maxn-10;
      t=s+1;
      n=read(),m=read(),k=read();
      for (int i=1;i<=m;i++)
      {
      	x[i]=read(),y[i]=read(),w[i]=read();
      }
      insert(s,1,k);
      insert(n,t,k);
      //dinic();
      int ansflow=k;
      ansflow-=dinic();
      for (int i=1;i<=1000000;i++)
      {
      	 for(int j=1;j<=m;j++) insert(x[j]+(i-1)*n,y[j]+i*n,w[j]);
      	 for(int j=1;j<=n;j++) insert(j+(i-1)*n,j+i*n,inf);
         insert(n+i*n,t,k);
         ansflow-=dinic();
         if(!ansflow) 
         {
         	cout<<i<<endl;
         	return 0;
         } 
         //cout<<i<<" "<<ansflow<<endl;
      }
      return 0;
    }
    
    
  • 相关阅读:
    MySQL之事务
    TP5之查询那些事
    TP5之上传多张图片
    PhpStorm之设置字体大小
    Git入门
    TP5之自定义分页样式
    TP之安全机制
    Navicat Premium连接服务器数据库
    IEnumerable 与 IEnumerable<T>
    关于递归
  • 原文地址:https://www.cnblogs.com/yimmortal/p/10163265.html
Copyright © 2011-2022 走看看