$[Luogu]$ 洛谷 $P3254$ 题解【圆桌问题】

终于过了,发篇题解庆祝一下

其实主要是因为被卡死了最后一个点来……

普度众生?

不存在的!只是想给大家JIO一下当前弧优化

如果大佬已经了解就请跳过蒟蒻的题解吧

这一题的建边并不难,SS向单位建一个流量为R_iRi的边,每个单位向每个桌子建一条流量为1的边,桌子向TT建一条流量为C_iCi的边就好啦

步入正题:

我们想一下,

如果有一个点出去了很多条边,那么在DFS中会有重复的遍历

出题人良心一点就会被卡的死死的

如何不被卡死!这是一个问题QAQ

不要跟我说卡常,我卡了半天也没卡进去

所以我们可以在分完层之后,跑完一次后就记录一下上一次跑的边

然后就可以优秀的跑过了

其实当前弧优化要修改的地方真的不多

上代码QAQ:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int head[100005],num_edge=-1,n,m,s,t,tot;
struct Edge
{
    int next,to,dis;
}edge[100005];
void add(int from,int to,int dis)
{
    edge[++num_edge].next=head[from];
    edge[num_edge].to=to;
    edge[num_edge].dis=dis;
    head[from]=num_edge;
}
int d[10001],q[10001],cur[10001];
bool bfs()
{
    int hea=0,tai=1;
    memset(d,0,sizeof(d));
    d[s]=1;
    q[1]=s;
    do
    {
        hea++;
        int x=q[hea];
        for(register int i=head[x];i!=-1;i=edge[i].next)
        {
            int y=edge[i].to;
            if(!d[y]&&edge[i].dis>0)
            {
                d[y]=d[x]+1;
                q[++tai]=y;
            }
        }
    }while(hea<tai);
    if(!d[t]) return 0;
    else return 1;
}
int dfs(int pos,int last)
{
    if(pos==t) return last;
    for(register int i=cur[pos];i!=-1;i=edge[i].next)//当前弧优化QAQ
      if(d[edge[i].to]==d[pos]+1&&edge[i].dis)
      {
        int data=dfs(edge[i].to,min(edge[i].dis,last));
        if(data>0)
        {
            edge[i].dis-=data;
            edge[i^1].dis+=data;
            if(edge[i].dis) cur[pos]=i;//当前弧优化QAQ
            return data;
        }
      }
    return 0;
}
inline int read()
{
    char ch='!';int z=1,num=0;
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')z=-1,ch=getchar();
    while(ch<='9'&&ch>='0')num=(num<<3)+(num<<1)+ch-'0',ch=getchar();
    return z*num;
}
inline int Dinic()
{
    int ans=0;
    while(bfs())
    {
        memcpy(cur,head,sizeof(cur));//当前弧优化QAQ
        while(int data=dfs(s,0x3f3f3f3f))
          ans+=data;
    }
    return ans;
}
int main(){
    memset(head,-1,sizeof(head));
    n=read();
    m=read();
    s=0;
    t=n+m+1;
    for(register int i=1;i<=n;++i)
    {
        int r;
        r=read();
        add(s,i,r);
        add(i,s,0);
        tot+=r;
    }
    for(register int i=1;i<=n;++i)
      for(register int j=1;j<=m;++j)
        add(i,j+n,1),add(j+n,i,0);
    for(register int i=1;i<=m;++i)
    {
        int c;
        c=read();
        add(i+n,t,c);
        add(t,i+n,0);
    }
    int maxflow=Dinic();
    if(maxflow!=tot){printf("0");return 0;}
    printf("1
");
    for(register int i=1;i<=n;++i)
    {
        for(register int j=head[i];j;j=edge[j].next)
          if(edge[j].dis==0&&edge[j].to!=0) printf("%d ",edge[j].to-n);
        printf("
");
    }
}
原文地址:https://www.cnblogs.com/wo-shi-zhen-de-cai/p/9787478.html