zoukankan      html  css  js  c++  java
  • $[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("
    ");
        }
    }
  • 相关阅读:
    架构设计:系统间通信(38)——Apache Camel快速入门(下1)
    打开文件
    求阶乘
    创建链表
    函数模板返回两个值的最小值,确保能正确处理字符串
    运算符重载两数组相加
    图书管理
    计算不同形状的面积
    不同人的信息,虚函数
    输出平面上三角形的面积
  • 原文地址:https://www.cnblogs.com/wo-shi-zhen-de-cai/p/9787478.html
Copyright © 2011-2022 走看看