zoukankan      html  css  js  c++  java
  • 洛谷 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;
    }
  • 相关阅读:
    P1843 奶牛晒衣服
    P1577 切绳子
    P2777 [AHOI2016初中组]自行车比赛——洛谷
    选择我自己的算法 2012年CCC加拿大高中生信息学奥赛
    如何修改博客园里个人首页背景(form:cot 大犇)
    洛谷P1105 平台
    SPFA模板板板板板板板板板板板板板板板板板板板板板板板板板板板板板板板板板板板板板板板板板板板板板板
    洛谷p2504 HAOI2006 聪明的猴子
    舒适的路线
    超级质数
  • 原文地址:https://www.cnblogs.com/lalalatianlalu/p/9809995.html
Copyright © 2011-2022 走看看