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

    每个球向可以组成的完全平方数连边,会连出一个有向无环图

    柱子上的球对应图上的路径,相当于最小路径点覆盖

    求出拆点二分图,再用n-最大匹配数即可

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<cmath>
    #define maxn 100000
    #define maxm 100000
    #define INF 0x7fffffff
    using namespace std;
    int n;
    struct edge{
        int from;
        int to;
        int next;
    }E[maxm*4+5];
    long long flow[maxm*4+5];
    int head[maxn*2+5];
    int sz=1;
    void add_edge(int u,int v,int w){
    //	if(u<v)printf("%d->%d %d
    ",u,v,w);
        sz++;
        E[sz].from=u;
        E[sz].to=v;
        E[sz].next=head[u];
        head[u]=sz;
        flow[sz]=w;
    }
    
    int deep[maxn*2+5];
    int bfs(int s,int t){
        queue<int>q;
        memset(deep,0,sizeof(deep));
        deep[s]=1;
        q.push(s);
        while(!q.empty()){
            int x=q.front();
            q.pop();
            for(int i=head[x];i;i=E[i].next){
                int y=E[i].to;
                if(flow[i]&&!deep[y]){
                    deep[y]=deep[x]+1;
                    q.push(y);
                    if(y==t) return 1;
                } 
            }
        }
        return 0;
    }
    
    int pre[maxn];
    long long dfs(int x,int t,long long minf){
        if(x==t) return minf;
        long long rest=minf,k;
        for(int i=head[x];i;i=E[i].next){
            int y=E[i].to;
            if(flow[i]&&deep[y]==deep[x]+1){
                k=dfs(y,t,min(rest,flow[i]));
                if(k==0){
                    deep[y]=0;
                    continue; 
                }
                flow[i]-=k;
                flow[i^1]+=k;
                rest-=k;
                pre[x/2]=y/2;
            }
        }
        return minf-rest;
    }
    
    long long dinic(int s,int t){
        long long maxflow,nowflow;
        maxflow=0;
        while(bfs(s,t)){
            while(nowflow=dfs(s,t,INF)){
                maxflow+=nowflow;
            }
        }
        return maxflow;
    }
    
    int is_sqr(int x){
        if(sqrt(x)==(double)x) return 1;
        else return 0; 
    }
    
    
    int tmp[maxn*2+5];
    int vis[maxn*2+5];
    int s=0,t=maxn+1;
    void print_ans(int x){
        for(int i=x;i!=0&&i!=t/2;i=pre[i]){
            vis[i]=1;
            printf("%d ",i);
        }
        printf("
    ");
    }
    int main(){
        scanf("%d",&n);
        int pil=0,ball=0;
    
        while(pil<=n){
            ball++;
            add_edge(s,ball*2,1);
            add_edge(ball*2+1,s,0);
            add_edge(ball*2+1,t,1);
            add_edge(t,ball*2+1,0);
            for(int i=sqrt(ball)+1;i*i<(ball*2);i++){
                add_edge((i*i-ball)*2,ball*2+1,1);
                add_edge(ball*2+1,(i*i-ball)*2,0);
            }
            int ans=dinic(s,t);
            if(!ans){
                tmp[++pil]=ball;
            }
        } 
        printf("%d
    ",ball-1);
        for(int i=1;i<=n;i++){
            print_ans(tmp[i]);
        }
        
    }
    
  • 相关阅读:
    看着四年前的代码,那时奋斗的模样,百感滋味
    操作系统中进程调度策略有哪几种?
    Linux操作系统及调用接口
    wpf 图像浏览(平移,缩放)
    C# double小数点的取舍
    C# 读写16位tif图片灰度数据
    WPF Slider滑块的使用
    WPF使用MVVMLight的ViewModel 访问控件的属性方法事件以及多页面传递信息
    苹果手机小米手环5收不到微信QQ消息提醒的解决办法
    AD覆铜设置规则
  • 原文地址:https://www.cnblogs.com/birchtree/p/10314627.html
Copyright © 2011-2022 走看看