• P2754 [CTSC1999]家园


    传送门

    人在各个太空站流动,所以显然的网络流模型

    因为不同时间能走的边不同,所以显然按时间拆点

    但是因为不知道要多少时间,所以要枚举时间,动态拆点

    每一点向下一个时间的同一点连流量为 $INF$ 的边,表示时间的转移

    因为知道时间,所以可以求出每站的下一站,流量显然就是对应太空船的容量

    每多一时间就拆一波点

    不用每次都把图重建,每次在残量网络上继续跑就好了

    当最大流大于或等于总人数时就的时间就是答案

    用并查集判断源点和汇点是否联通,判断是否有解

    时间复杂度$O(能过)$,空间复杂度玄学

    跑得还挺快...

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    using namespace std;
    typedef long long ll;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x*f;
    }
    const int N=2e5+7,INF=1e9+7;
    int fir[N],from[N<<2],to[N<<2],val[N<<2],cntt=1;
    inline void add(int a,int b,int c)
    {
        from[++cntt]=fir[a]; fir[a]=cntt;
        to[cntt]=b; val[cntt]=c;
        from[++cntt]=fir[b]; fir[b]=cntt;
        to[cntt]=a; val[cntt]=0;
    }
    int n,m,K,S,T,tot;
    int dep[N];
    queue <int> q;
    bool BFS()
    {
        for(int i=0;i<=tot;i++) dep[i]=0;
        q.push(S); dep[S]=1;
        while(!q.empty())
        {
            int x=q.front(); q.pop();
            for(int i=fir[x];i;i=from[i])
            {
                int &v=to[i]; if(dep[v]||!val[i]) continue;
                dep[v]=dep[x]+1; q.push(v);
            }
        }
        return dep[T] ? 1 : 0;
    }
    int DFS(int x,int mif)
    {
        if(x==T||!mif) return mif;
        int fl=0,res=0;
        for(int i=fir[x];i;i=from[i])
        {
            int &v=to[i]; if(dep[v]!=dep[x]+1) continue;
            if( res=DFS(v,min(mif,val[i])) )
            {
                fl+=res; mif-=res;
                val[i]-=res; val[i^1]+=res;
                if(!mif) break;
            }
        }
        return fl;
    }
    //以上最大流模板
    struct Ship{//存太空船的信息
        int sz,t;//容纳人数和经过站点的数量
        vector <int> v;//太空船经过的太空站
    }p[233];
    int fa[N];//并查集
    inline int find(int x) { return x==fa[x] ? x : fa[x]=find(fa[x]); }
    int ans,mxf;
    int main()
    {
        n=read()+2,m=read(),K=read();
        for(int i=1;i<=n;i++) fa[i]=i;
        for(int i=1;i<=m;i++)
        {
            p[i].sz=read(),p[i].t=read();
            for(int j=1;j<=p[i].t;j++)
            {
                int a=read();
                if(a==-1) a=n;
                if(a==0) a=n-1;
                p[i].v.push_back(a);
            }
            for(int j=1;j<p[i].t;j++)
            {
                int xa=find(p[i].v[j]),ya=find(p[i].v[0]);
                if(xa!=ya) fa[xa]=ya;
            }
        }
        if(find(n-1)!=find(n)) { printf("0"); return 0; }
        S=n-1; tot=n;
        while(1)//枚举时间
        {
            for(int i=1;i<=n;i++) add(tot-n+i,tot+i,INF);
            for(int i=1;i<=m;i++)
                add(tot-n+p[i].v[ ans%p[i].t ],tot+p[i].v[ (ans+1)%p[i].t ],p[i].sz);
            tot+=n; T=tot; ans++;
            while(BFS()) mxf+=DFS(S,INF);
            if(mxf>=K) break;
        }
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    Java知识系统回顾整理01基础05控制流程02 switch
    Java知识系统回顾整理01基础05控制流程01if
    Java知识系统回顾整理01基础04操作符07Scanner
    Java知识系统回顾整理01基础04操作符06三元运算符
    Java知识系统回顾整理01基础04操作符05赋值操作符
    Java知识系统回顾整理01基础04操作符04位操作符
    Java知识系统回顾整理01基础04操作符03逻辑运算符
    leetcode-----74. 搜索二维矩阵
    leetcode-----73. 矩阵置零
    leetcode-----72. 编辑距离
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/10351448.html
Copyright © 2020-2023  润新知