zoukankan      html  css  js  c++  java
  • [网络流24题] 魔术球问题

    本来是cogs上面的题来着,但是现在上不去了。
    题目链接:戳我
    听说贪心可做,打表找规律可做(都是些什么神奇做法啊,这难道不是让我们用网络流做的吗喂
    最大流一类转化的问题。建图是关键。
    题目的大概意思:用最少的柱子放1-n个球,要求同一根柱子上两个相邻的球数值之和为完全平方数。n要尽可能地大。其实我们读了题目之后是不是能想到最小路径覆盖(不相交)呢?
    如果不会DAG最小路径覆盖的可以戳这里看看。(蒟蒻推广一波博客qwqwq大家翻一下能找到)
    有一个定理就是最小路径覆盖数=节点个数-最大匹配,证明我在博客里写的有。
    那么思路就请清晰了,拆点肯定是必不可少的。如果要连边,肯定是u1->v2。然后因为每个球有两种状态,一种是自己新开一个柱子放,一种是从其他球那里承接过来。最后记得每个点分别向S和T连边。
    emmmm如果你问我怎么确定球地上限呢?我也不知道,大家去看别的大佬的博客上好像是有证明的,我只是按着一般网络流能处理的数据范围写的啦qwq
    具体细节看代码吧qwq
    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define MAXN 100010
    #define EX 2333
    #define S 0
    #define T 5010
    using namespace std;
    int n,t=1,ans;
    int head[MAXN],dis[MAXN],cur[MAXN],to[MAXN],done[MAXN];
    bool issqr[MAXN];
    struct Edge{int nxt,to,dis;}edge[MAXN];
    inline void add(int from,int to,int dis)
    {
        edge[++t].nxt=head[from],edge[t].to=to,edge[t].dis=dis,head[from]=t;
        edge[++t].nxt=head[to],edge[t].to=from,edge[t].dis=0,head[to]=t;
    }
    inline void addedge(int x)
    {
        for(int i=1;i<x;i++) 
            if(issqr[i+x])
                add(i,x+EX,1);
        add(S,x,1);
        add(x+EX,T,1);
    }
    inline bool bfs()
    {
        queue<int>q;
        memset(dis,0x3f,sizeof(dis));
        memcpy(cur,head,sizeof(head));
        q.push(S);dis[S]=0;
        while(!q.empty())
        {
            int u=q.front();q.pop();
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int v=edge[i].to;
                if(dis[v]==0x3f3f3f3f&&edge[i].dis)
                    dis[v]=dis[u]+1,q.push(v);
            }
        }
        if(dis[T]==0x3f3f3f3f) return false;
        return true;
    }
    inline int dfs(int x,int f)
    {
        if(!f||x==T) return f;
        int used=0,w;
        for(int i=cur[x];i;i=edge[i].nxt)
        {
            int v=edge[i].to;
            cur[x]=i;
            if(dis[v]==dis[x]+1&&(w=dfs(v,min(edge[i].dis,f))))
            {
                used+=w,f-=w;
                edge[i].dis-=w,edge[i^1].dis+=w;
                to[x]=v;
                if(!f) break;
            }
        }
        return used;
    }
    
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d",&n);
        int c;
        for(int i=1;i<=100;i++) c=i*i,issqr[c]=1;
        for(int i=1;i<=5000;i++)
        { 
            addedge(i);
            while(bfs())
                ans+=dfs(S,(int)1e9);
            if(i-ans>n){ans=i-1;break;}
        }
        printf("%d
    ",ans);
        to[0]=0;
        for(int i=1;i<=ans;i++)
        {
            if(done[i]==1) continue;
            printf("%d ",i);done[i]=1;
            int now=to[i]>ans?to[i]-EX:to[i]; done[now]=1;
            while(now!=0)
            {
                printf("%d ",now); 
                now=to[now]>ans?to[now]-EX:to[now];done[now]=1;
            }
            printf("
    ");
        }
        return 0;
    }
    
    
  • 相关阅读:
    禁止360开机自动启动
    Google Code注册方法详解 Google Code网盘申请方法
    做程序开发工作,编程思想很重要
    EPP(Eclipse PHP)语法高亮仿EditPlus配置
    2HC32F460(华大)+BC260Y(NBIOT)基本控制篇(自建物联网平台)整体运行测试微信小程序扫码绑定BC260Y(NBIOT),并通过MQTT和单片机实现远程通信控制
    2HC32F460(华大)+BC260Y(NBIOT)基本控制篇(自建物联网平台)整体运行测试Android扫码绑定BC260Y(NBIOT),并通过MQTT和单片机实现远程通信控制
    【面向对象】宽接口、窄接口和访问方法(上)
    重构,小步进行曲
    Java中有些好的特性(一):静态导入
    【读书笔记】设计模式沉思录
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10294687.html
Copyright © 2011-2022 走看看