$[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\n");
    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("\n");
    }
}

 

转载于:https://www.cnblogs.com/wo-shi-zhen-de-cai/p/9787478.html

题目描述似乎缺失了关键信息,通常我会需要了解“P10780 食物”是什么具体的算法竞赛题目,它来自在线平台洛谷Luogu),以及该题目的大致背景、条件和目标。洛谷食物(Food)可能是某种数据结构或算法问题,比如贪吃蛇、分配任务等。 然而,我可以给你提供一个通用的模板: **[洛谷 P10780 食物 - 题目解析]** 题目名称:P10780 食物(假设是关于食物分配或者饥饿游戏的问题) 链接:[插入实际题目链接] **背景:** 此题通常涉及动态规划或者搜索策略。场景可能是有n个参与者(选手或角色),每个都有特定的食物需求或者优先级,我们需要在有限的食物资源下合理分配。 **分析:** 1. **输入理解**:首先读入n个参与者的信息,包括每个人的需求量或优先级。 2. **状态定义**:可以定义dp[i][j]表示前i个人分配完成后剩余的食物能满足第j个人的最大程度。 3. **状态转移**:递推式可能涉及到选择当前人分配最多食物的版本,然后更新剩余的食物数。 4. **边界条件**:如果剩余食物不足以满足某人的需求,则考虑无法分配给他;如果没有食物,状态值设为0。 5. **优化策略**:可能需要对状态数组进行滚动更新,以减少空间复杂度。 **代码示例(伪代码或部分关键代码片段):** ```python # 假设函数分配_food(demand, remaining)计算分配给一个人后剩余的食物 def solve(foods): dp = [[0 for _ in range(max_demand + 1)] for _ in range(n)] dp = foods[:] # 从第一个到最后一个参与者处理 for i in range(1, n): for j in range(1, max_demand + 1): if dp[i-1][j] > 0: dp[i][j] = max(dp[i][j], dp[i-1][j] - foods[i]) dp[i][j] = max(dp[i][j], distribute_food_to(i, dp[i-1][j])) return dp[n-1][max_demand] ``` **相关问题--:** 1. 这道题是如何运用动态规划的? 2. 如果有优先级限制,应该如何调整代码? 3. 怎样设计搜索策略来解决类似问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值