• 洛谷 P2765 魔术球问题(网络流24题-最大流)


    题意:中文题(lrj黑书上好像有这道题)

    思路:这个题的建图还真的是挺有意思的,我们把一个球拆成2个点a,b。 然后让a点连S点,b点连T点,如果有两个数的加和为平方数,那我们就用第一个数的a点连向第二个数的b点,这样就有一条流直接流向汇点T

    代码:(顺便get了怎么打印路径,赋学习传送门

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long LL;
    inline LL read()
    {
        LL x=0,f=1;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    
    struct Edge{
        int next,to,f;
    };
    struct Dinic
    {
        int s,t;
        Edge e[1000010];
        int cnt=2,head[1000010]={0};
        int dis[1000010]={0};
        Dinic (){}
        void init(int _s,int _t)
        {
            cnt=2;
            s=_s,t=_t;
            memset(head,0,sizeof(head));
        }
        void addedge(int u,int v,int f)
        {
            e[cnt]={head[u],v,f};
            head[u]=cnt++;
            e[cnt]={head[v],u,0};
            head[v]=cnt++;
        }
        bool bfs()
        {
            memset(dis,0,sizeof(dis));
            dis[s]=1;
            queue<int> q;
            q.push(s);
            while(!q.empty())
            {
                int u=q.front();
                q.pop();
                for(int i=head[u];i;i=e[i].next)
                {
                    int v=e[i].to;
                    if(!dis[v]&&e[i].f>0)
                    {
                        dis[v]=dis[u]+1;
                        q.push(v);
                    }
                }
            }
            return dis[t]!=0;
        }
    
        int dfs(int u,int flow)
        {
            if(u==t||flow==0) return flow;
            int flow_sum=0;
            for(int i=head[u];i;i=e[i].next)
            {
                int v=e[i].to,f=e[i].f;
                if(dis[v]!=dis[u]+1||f==0) continue;
                int temp=dfs(v,min(flow-flow_sum,f));
                e[i].f-=temp;
                e[i^1].f+=temp;
                flow_sum+=temp;
                if(flow_sum>=flow) break;
            }
            if(!flow_sum) dis[u]=-1;
            return flow_sum;
        }
    
        int maxflow()
        {
            int ans=0;
            while(bfs())
            {
                while(int temp=dfs(s,0x7fffffff))
                    ans+=temp;
            }
            return ans;
        }
    }DC;
    
    int vis[20050];
    int main()
    {
        int n=read();
        int ball;
        int cnt=0;
        int s=0,t=20000;
        DC.init(s,t);
        for(cnt=0,ball=1;cnt<=n;cnt++){
            if(cnt){
                ball++;
            }
            for(;;ball++){
                DC.addedge(s,ball,1);
                DC.addedge(ball+10000,t,1);
                for(int i=1;i<ball;i++){
                    if(sqrt(ball+i)==(int)sqrt(ball+i)){
                        DC.addedge(i,ball+10000,1);
                    }
                }
                int as=DC.maxflow();
                if(!as)break;
            }
        }
        printf("%d",ball-1);
        for(int i=1;i<=ball-1;i++){
            if(vis[i])continue;
            vis[i]=true;cout<<endl<<i<<' ';
            int k=i;
            while(true){
                bool ok=false;
                for(int i=DC.head[k];i;i=DC.e[i].next){
                    int v=DC.e[i].to,f=DC.e[i].f;
                    if(v>10000&&f==0){
                        cout<<v-10000<<' ';
                        vis[v-10000]=true;
                        k=v-10000;ok=true;
                        break;
                    }
                }
                if(!ok)break;
            }
        }
        return 0;
    }
  • 相关阅读:
    [洛谷P4774] [NOI2018]屠龙勇士
    [洛谷P3338] [ZJOI2014]力
    [洛谷P1707] 刷题比赛
    svn查看指定版本提交信息的命令
    ajax无刷新上传文件
    给docker里的php安装gd扩展
    PHP基于openssl实现的非对称加密操作
    php获取文件扩展名
    javascript格式化日期
    javascript获取url参数
  • 原文地址:https://www.cnblogs.com/lalalatianlalu/p/9809995.html
Copyright © 2020-2023  润新知