[CTSC1999]家园

题意简化

给定几趟循环移动的载客列车与站点数量,求所有人从第1站到最后一站的时间

题目链接

题解

这个题一开始确实比较难想,因为这题数据规模奇小,我们可以直接根据每一单位时间建图。

也就是说,第一步先建立虚拟原点汇点之后,将地球和月亮与其连边,然后每一天的每一趟车所在点向它下一天的所在点连一条容量为载客量的边,然后要把每一天的每个点向下一天连一条容量为inf的边(因为可以等嘛)

然后就是裸的最大流了,dinic,EK都行

代码


#include<bits/stdc++.h>
using namespace std;
#define re register
#define in inline
#define ll long long
#define get getchar()
in int read()
{
    int t=0,x=1; char ch=get;
    while((ch<'0' || ch>'9') && ch!='-') ch=get;
    if(ch=='-') ch=get,x=-1;
    while(ch<='9' && ch>='0') t=t*10+ch-'0',ch=get;
    return t*x;
}
const int inf=0x3f3f3f3f;
const int _=60001;
const int MAXN=55;
struct edge{
    int to,ne,w;
}e[_<<2];
int tot=-1,S=50000,T=50001,head[_],h[MAXN],cyc[MAXN][MAXN],r[MAXN],n,m,k,dep[_],vis[_];
in void add(int x,int y,int z)
{
    e[++tot].ne=head[x],e[tot].to=y,e[tot].w=z,head[x]=tot;
    e[++tot].ne=head[y],e[tot].to=x,e[tot].w=0,head[y]=tot;
}
in bool bfs()
{
    memset(dep,0x3f,sizeof(dep));
    memset(vis,0,sizeof(vis));
    queue<int >q;
    q.push(S);
    dep[S]=0;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(re int i=head[u];i!=-1;i=e[i].ne)
        {
            int v=e[i].to;
            if(e[i].w && dep[v]>dep[u]+1)
            {
                dep[v]=dep[u]+1;
                if(!vis[v]) {
                    vis[v]=1;
                    q.push(v);
                }
            }
        }
    }
    return dep[T]!=0x3f3f3f3f;
    
}
in int dfs(int u,int flow)
{
    int rlow=0;
    if(u==T)
        return flow;
    int used=0;
    for(re int i=head[u];i!=-1;i=e[i].ne)
    {
        int v=e[i].to;
        if(e[i].w&&dep[v]==dep[u]+1) {
            if(rlow=dfs(v,min(flow-used,e[i].w)))
            {
                used+=rlow;
                e[i].w-=rlow;
                e[i^1].w+=rlow;
                if(rlow==flow) break;
            }
        }
    }
    return used;
}
in int dinic()
{
    int ans=0;
    while(bfs())
       ans+=dfs(S,inf);
    return ans;
}
int main()
{
    memset(head,-1,sizeof(head));
    n=read(),m=read(),k=read();
    n+=2;
    for(re int i=1;i<=m;i++) {
        h[i]=read();
        r[i]=read();
        for(re int j=0;j<r[i];j++) {
            cyc[i][j]=read()+2;
        }
    }
    int Time=0,sum=0;
    while(Time<=500)
    {
        add(S,Time*n+2,inf);
        add(Time*n+1,T,inf);
        if(Time!=0){
        for(re int i=1;i<=m;i++)
        {
            int x=cyc[i][(Time-1)%r[i]],y=cyc[i][((Time)%r[i])];
            add(x+(Time-1)*n,y+(Time)*n,h[i]);
        }
        for(re int i=1;i<=n;i++) add(i+(Time-1)*n,i+(Time)*n,inf);
        }
        sum+=dinic();
        if(sum>=k) {cout<<Time<<endl;return 0;}
        Time++;
    }
    printf("0\n");
    return 0;
}

posted @ 2020-01-18 17:26  yzhx  阅读(136)  评论(0编辑  收藏  举报