洛谷P2765魔术球问题 最小路径覆盖

https://www.luogu.org/problemnew/show/P2765

看到这一题第一眼想到:这不是二分最大流吗,后来发现还有一种更快的方法。

首先如果知道要放多少个球求最少的柱子,很显然是一道最小点路径覆盖的题,将一个点拆成u,v两个点,u和S相连,v和T相连,之后的有向边i,就用ui和vj相连即可。

但是这题首先不知道有多少个球,所以考虑依次加入点以及和这个点相关的边,然后在残余网络上跑新的最大流,如果可以跑出流量来意味着这个点成功在现有的柱子上按排上了,如果跑不出来说明按排不上,需要重新开一根柱子放这个点。

 

直到跑到答案k的时候,柱子数超过了n,要的答案就是k - 1,至于方案,只要在最后的残余网络图上面搜索一下每个点的前驱即可。

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)  
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))  
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);  
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);  
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long  
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second 
typedef vector<int> VI;
int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();}
while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;}
const double eps = 1e-9;
const int maxn = 3010;
const int maxm = 80010;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7; 
int N,M,K;
int a[maxn];
struct Edge{
    int to,next,cap,flow;
    Edge(){}
    Edge(int to,int next,int cap,int flow):to(to),next(next),cap(cap),flow(flow){}
}edge[maxm * 2];
int head[maxn * 2],dis[maxn * 2],pre[maxn * 2],nxt[maxn * 2],vis[maxn * 2];
int n,s,tot,t;
void init(int N,int S,int T){
    n = N;s = S;t = T;
    for(int i = 0 ; i <= n ; i ++) head[i] = -1;
    tot = 0;
}
void add(int u,int v,int w){
    edge[tot] = Edge(v,head[u],w,0);
    head[u] = tot++;
    edge[tot] = Edge(u,head[v],0,0);
    head[v] = tot++;
}
bool BFS(){
    for(int i = 0 ; i <= n; i ++) dis[i] = -1;
    queue<int>Q;
    dis[s] = 0; Q.push(s);
    while(!Q.empty()){
        int u = Q.front(); Q.pop();
        for(int i = head[u]; ~i ; i = edge[i].next){
            int v = edge[i].to;
            if(~dis[v] || edge[i].cap <= edge[i].flow) continue;
            dis[v] = dis[u] + 1;
            Q.push(v);
        }
    }
    return ~dis[t];
}
int dfs(int u,int a){
    if(u == t || !a) return a;
    int flow = 0;
    for(int &i = pre[u]; ~i ; i = edge[i].next){
        int v = edge[i].to;
        if(dis[u] + 1 != dis[v]) continue;
        int f = dfs(v,min(a,edge[i].cap - edge[i].flow));
        if(!f) continue;
        a -= f; flow += f;
        edge[i].flow += f;
        edge[i ^ 1].flow -= f;
    }
    return flow;
}
int maxflow(){
    int flow = 0;
    while(BFS()){
        for(int i = 0 ; i <= n ;  i ++) pre[i] = head[i];
        flow += dfs(s,INF);
    }
    return flow;
}
void search(int t){
    for(int i = 1; i <= t; i ++){
        for(int j = head[i]; ~j ; j = edge[j].next){
            int v = edge[j].to;
            if(v == s) continue;
            if(edge[j].flow){
                nxt[i] = v - maxn;
                vis[v - maxn] = 1;
            } 
        }
    }
    for(int i = 1; i <= t; i ++){
        if(!vis[i]){
            for(int j = i; j; j = nxt[j]){
                printf("%d ",j);
            }
            puts("");
        }
    }
}
int main(){
    Sca(N);
    for(int i = 1; i <= 60; i ++) a[i] = i * i;
    int S = 6001,T = 6002;
    init(6002,S,T);
    int num = 0,k;
    int cnt = 1;
    for(k = 1;num <= N; k ++){
        while(k + k > a[cnt + 1]) cnt++;
        add(S,k,1);
        add(k + maxn,T,1);
        for(int i = cnt ; i >= 1; i --){
            if(a[i] - k <= 0) break;
            add(a[i] - k,k + maxn,1);
        }
        if(!maxflow()) num++;
    } 
    k-=2; num--;
    Pri(k);
    search(k);
    return 0;
}

 

posted @ 2019-02-03 10:51  Hugh_Locke  阅读(196)  评论(0编辑  收藏  举报