「网络流 24 题」魔术球

假如想象 提交于 2020-01-22 01:29:01

比较有意思的题

题意:给你n个柱子,问你可以在上面放多少个编号连续且每根柱子上相邻的编号为平方数的球
洗澡时候想的,根据平方数这个关系建边,然后枚举多少个柱子,然后再在图上跑最小路径覆盖,若路径条数大于柱子数,那么珠子数-1就是答案

我写的有点....t了,但不想改

#include<bits/stdc++.h>
using namespace std;

int n,tot=-1,h[3005],ans=0,hou[3005];
struct node{
    int from,next,to,rest,full;
    int last;
}e[1000005];
bool judge[60005];
void add(int x,int y,int z){
    tot++;
    e[tot].next=h[x];
    h[x]=tot;
    e[tot].from=x;
    e[tot].to=y;
    e[tot].rest=z;
    e[tot].full=z;
}

int dis[3005],g[3005],flow[3005];
bool vis[3005];

int bfs(int s,int t){
    queue<int>q;
    dis[s]=0;
    q.push(s);vis[s]=true;
    while(!q.empty()){
        int u=q.front();vis[u]=false;q.pop();
        for(int i=h[u];i!=(-1);i=e[i].next){
            if(dis[e[i].to]>dis[u]+1&&g[e[i].to]==(-1)&&e[i].rest>0){
                g[e[i].to]=i;
                flow[e[i].to]=min(flow[u],e[i].rest);
                dis[e[i].to]=dis[u]+1;
                if(vis[e[i].to]==false){
                    vis[e[i].to]=true;
                    q.push(e[i].to);
                }
            }
        }
    }
}

int EK(int s,int t){
    while(1){
        memset(dis,0x7f,sizeof(dis));
        memset(flow,0x7f,sizeof(flow));
        memset(g,-1,sizeof(g));
        bfs(s,t);
        if(g[t]==(-1))return 0;
        ans+=flow[t];
        for(int p=t;p!=(s);p=e[g[p]].from){
            e[g[p]].rest-=flow[t];
            e[g[p]^1].rest+=flow[t];
        }    
        
    }
}

int main(){
    memset(vis,false,sizeof(vis));
    memset(h,-1,sizeof(h));
    memset(hou,-1,sizeof(hou));
    cin>>n;
    int jy;
    for(int i=1;;i++){
        //cout<<i<<endl;
        int hj=4;
        for(int j=0;j<=tot;j++)e[j].rest=e[j].full;
        for(int j=1;j<i;j++){
            if(int(sqrt(j+i))*int(sqrt(j+i))==j+i){
                hj+=2;
                add(j,i+1500,1);
                add(i+1500,j,0);
            }
        }
        add(0,i,1);
        add(i,0,0);
        add(i+1500,3000,1);
        add(3000,i+1500,0);
        ans=0;
        EK(0,3000);
        if(i-ans>n){
            /*for(int j=0;j<=tot;j++){
            if(e[j].from==i||e[j].to==i||e[j].to==i+1234||e[j].from==i+1234){
                e[j].rest=0;
                e[j].full=0;        
                }
            }*/
            for(int j=0;j<hj;j++){
                h[e[tot-j].from]=e[tot-j].next;
            }
            jy=i-1;
            cout<<i-1<<endl;;
            break;
        }
        
    }
    
        for(int j=0;j<=tot;j++)e[j].rest=e[j].full;
        ans=0;
        EK(0,3000);
            for(int j=1;j<=jy;j++){
                for(int k=h[j];k!=(-1);k=e[k].next){
                    if(e[k].to!=0&&e[k].rest==0){
                        hou[j]=e[k].to-1500;
                        break;
                    }
                }
            }
            for(int j=1;j<=jy;j++){
                if(judge[j]==false){
                    cout<<j;judge[j]=true;
                    for(int now=hou[j];now!=(-1);now=hou[now]){
                        cout<<" "<<now;
                        judge[now]=true;
                    }
                    cout<<endl;
                }
            }
}
View Code
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!