BUPT 2022 Summer Training #1(2018 ICPC Asia Singapore Regional)

K - Conveyor Belts

题目大意:一共有N个节点M条边,在前K个点中,编号为j的节点会在第(xK+j)分钟产出物品(x0 and j=1,2,,K),物品通过一条边的时间为1分钟,最终通过传送带运输到仓库N,求在这K个节点中最多能保持多少个节点运行而不会产生冲突(即不会在某分钟有两个及以上的物品出现在同一个节点)。

数据范围:1KN300; 0M1000

解题思路:最大流。

对每个节点拆分成K个节点,表示每个节点在第i分钟的情况,若某条边连接x和y,则对x的第i分钟与y的第i+1分钟建立一条权值为1的边(若i=K则对x的第K分钟与y的第1分钟建边),源点对于前K个节点的产出物品时间建立权值为1的边,对n节点的所有K分钟建立流向汇点权值为inf的边。(一定要是inf,因为仓库是可以两个及以上的物品同时到达)接着跑最大流即可。

赛后总结:赛时知道是网络流,思路其实也差不多出来了,但是感觉有问题(也有时间原因)就没再往下想下去。

参考代码:

#include<bits/stdc++.h>
using namespace std;
long long head[250000],num1=1,n,k,m,s,t,ans,deep[100000];
struct tu{
    long long next,to,sco;
}e[3000000];
void work(long long from,long long to,long long sco)
{
    e[++num1].next=head[from];
    e[num1].to=to;
    e[num1].sco=sco;
    head[from]=num1;
}
bool bfs()
{
    memset(deep,0,sizeof(deep));
    queue<long long> line;
    deep[s]=1;
    line.push(s);
    while(!line.empty())
    {
        long long now=line.front();
        line.pop();
        for(long long i=head[now];i;i=e[i].next)
        {
            if(e[i].sco&&!deep[e[i].to])
            deep[e[i].to]=deep[now]+1,line.push(e[i].to);
        }
    }
    return deep[t];
}
long long dfs(long long now,long long in)
{
    if(now==t)
    return in;
    long long out=0;
    for(long long i=head[now];i&&in;i=e[i].next)
    {
        if(e[i].sco&&deep[e[i].to]==deep[now]+1)
        {
            long long res=dfs(e[i].to,min(in,e[i].sco));
            in-=res;
            out+=res;
            e[i].sco-=res;
            e[i^1].sco+=res;
        }
    }
    if(out==0)
    deep[now]=0;
    return out;
}
int main()
{
    cin>>n>>k>>m;
    for(long long i=1;i<=m;i++)
    {
        long long u,v;
        scanf("%lld%lld",&u,&v);
        for(long long j=0;j<k;j++)
        {
            long long from=u*k+j,nt=v*k+j+1;
            if(j==k-1)
            nt-=k;
            work(from,nt,1);
            work(nt,from,0);
        }
    }
    s=(n+1)*k,t=(n+1)*k+1;
    for(long long i=1;i<=k;i++)
    {
        work(s,i*k+(i-1),1);
        work(i*k+(i-1),s,0);
    }
    for(long long i=1;i<=k;i++)
    {
        work(n*k+(i-1),t,1e9);
        work(t,n*k+(i-1),0);
    }
    while(bfs())
    {
        ans+=dfs(s,1e18);
    }
    cout<<ans<<endl;
    return 0;
}

 

posted @ 2022-07-13 14:14  hongyubin  阅读(45)  评论(0)    收藏  举报