zoukankan      html  css  js  c++  java
  • dtoi2797 旅行商

    题意:

         camp国有n座城市,由1,2,...,n编号。城市由n–1条双向道路相连。任意两个城市之间存在唯一的道路连通。有m个旅行商,第i个旅行商会从城市ai旅行到城市bi,贩卖ci件商品。已知第i个城市的居民最多购买wi件商品,bobo想知道旅行商们能够卖出商品数量的最大值。

         n,m<=20000。

    题解:

         考虑暴力,对于每一个旅行商,将其路径上的所有点都连边,然后跑最大流就可以了。不过边数太多了,会TLE。

         那么这没有什么关系,我们可以树剖+线段树,将每个旅行商连向他们所对应的节点,容量为INF即可。当然每个线段树节点也都要向各自的城市连边。

         这样的话,边数就优化成了m*logn*logn,再跑最大流,可以通过这道题。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<vector>
    #include<queue>
    using namespace std;
    const int INF=2e9;
    typedef struct{
        int w,zjds,xzd,dep,dfn,twz;
    }P;
    P p[20002];
    int n,m,fa[22][20002],d[100005],cur[100005],cnt,hh=80000,s=100001,t=100002,df[20002];
    vector<int>g[20002];
    struct Edge{
        int from,to,cap,flow;
        Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}
    };
    vector<int>c[100005];
    vector<Edge>edges;
    void add(int u,int v,int w){
        edges.push_back(Edge(u,v,w,0));
        edges.push_back(Edge(v,u,0,0));
        c[u].push_back(edges.size()-2);
        c[v].push_back(edges.size()-1); 
    }
    bool bfs(int s){
        queue<int>q;memset(d,-1,sizeof(d));
        q.push(s);d[s]=0;
        while(!q.empty())
        {
            int u=q.front();q.pop();
            for (int i=0;i<c[u].size();i++)
            {
                Edge e=edges[c[u][i]];
                if (e.cap>e.flow && d[e.to]==-1)
                {
                    q.push(e.to);d[e.to]=d[u]+1;
                    if (e.to==t)return true;
                }
            }
        }
        return false;
    }
    int dfs(int x,int a){
        if (x==t)return a;
        int flow=0,f;
        for (int& i=cur[x];i<c[x].size();i++)
        {
            Edge& e=edges[c[x][i]];
            if (e.cap>e.flow && d[x]+1==d[e.to] && (f=dfs(e.to,min(a,e.cap-e.flow)))>0)
            {
                flow+=f;a-=f;
                e.flow+=f;edges[c[x][i]^1].flow-=f;
            }
            if (!a)break;
        }
        return flow;
    }
    void dfs1(int x,int faa,int deep){
        int Max=0,maxn=-1;p[x].zjds=1;fa[0][x]=faa;p[x].dep=deep;
        for (int i=0;i<g[x].size();i++)
        if (g[x][i]!=faa)
        {
            dfs1(g[x][i],x,deep+1);p[x].zjds+=p[g[x][i]].zjds;
            if (p[g[x][i]].zjds>Max)
            {
                Max=p[g[x][i]].zjds;maxn=g[x][i];
            }
        }
        p[x].xzd=maxn;
    }
    void dfs2(int x,int fa){
        p[x].dfn=++cnt;if (p[fa].xzd==x)p[x].twz=p[fa].twz;else p[x].twz=x;
        df[cnt]=x;
        if (p[x].xzd!=-1)dfs2(p[x].xzd,x);
        for (int i=0;i<g[x].size();i++)
        if (g[x][i]!=fa && g[x][i]!=p[x].xzd)dfs2(g[x][i],x);
    }
    int lca(int x,int y){
        if (p[x].dep<p[y].dep)swap(x,y);
        int k=p[x].dep-p[y].dep;
        for (int i=0;i<=20;i++)
        if (k&(1<<i))x=fa[i][x];
        if (x==y)return x;
        for (int i=20;i>=0;i--)
        if (fa[i][x]!=fa[i][y])
        {
            x=fa[i][x];y=fa[i][y];
        }
        return fa[0][x];
    }
    void build(int root,int begin,int end){
        if (begin==end)
        {
            add(s,root,p[df[begin]].w);return;
        }
        int mid=(begin+end)/2;
        build(root*2,begin,mid);build(root*2+1,mid+1,end);
        add(root*2,root,INF);add(root*2+1,root,INF);
    }
    void gengxin(int root,int begin,int end,int begin2,int end2,int wz){
        if (begin>end2 || end<begin2)return;
        if (begin>=begin2 && end<=end2)
        {
            add(root,hh+wz,INF);return;
        }
        int mid=(begin+end)/2;
        gengxin(root*2,begin,mid,begin2,end2,wz);gengxin(root*2+1,mid+1,end,begin2,end2,wz);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++)scanf("%d",&p[i].w);
        for (int i=1;i<n;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);g[x].push_back(y);g[y].push_back(x);
        }
        dfs1(1,0,1);dfs2(1,0);
        for (int i=1;i<=20;i++)
        for (int j=1;j<=n;j++)
        fa[i][j]=fa[i-1][fa[i-1][j]];
        build(1,1,n);
        for (int i=1;i<=m;i++)
        {
            int u,v,lc,h;
            scanf("%d%d%d",&u,&v,&h);
            lc=lca(u,v);
            while(p[u].dep>=p[lc].dep)
            {
                if (p[p[u].twz].dep<p[lc].dep)gengxin(1,1,n,p[lc].dfn,p[u].dfn,i);
                else
                {
                    gengxin(1,1,n,p[p[u].twz].dfn,p[u].dfn,i);
                }
                u=fa[0][p[u].twz];
            }
            while(p[v].dep>=p[lc].dep)
            {
                if (p[p[v].twz].dep<p[lc].dep)gengxin(1,1,n,p[lc].dfn,p[v].dfn,i);
                else
                {
                    gengxin(1,1,n,p[p[v].twz].dfn,p[v].dfn,i);
                }
                v=fa[0][p[v].twz];
            }
            add(hh+i,t,h);
        }
        int ans=0;
        while(bfs(s)){memset(cur,0,sizeof(cur));ans+=dfs(s,INF);}
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    sock文件
    Django---数据迁移
    Linux磁盘占满 no space left on device
    Linux关闭防火墙命令
    linux系统搭建zookeeper集群
    Linux下安装zookeeper-3.4.13
    CentOS7.5安装JDK1.8
    CentOS下搭建NFS服务器总结
    NFS客户端挂载目录后无写入权限的解决方案
    centos关机与重启命令
  • 原文地址:https://www.cnblogs.com/1124828077ccj/p/12253699.html
Copyright © 2011-2022 走看看