zoukankan      html  css  js  c++  java
  • CodeForces 1045A. Last chance(线段树+网络流SAP)

    网络流,对三种武器分别有不同建图的方法,核心宗旨是:源点->武器->飞船->汇点。

    • SQL rockets – every SQL rocket can destroy at most one spaceship in the given set.
    • Cognition beams – every Cognition beam has an interval [l,r],and can destroy at most one spaceship in that interval.
    • OMG bazooka – every OMG bazooka has three possible targets, however, each bazooka can destroy either zero or exactly two spaceships. In addition, due to the smart targeting system, the sets of the three possible targets of any two different OMG bazookas are disjoint (that means that every ship is targeted with at most one OMG bazooka).

    因为题目种对三种武器做了如下规定:

    1.SQL rockets:ΣK <=100000,可以直接建图。

    2.[l,r]中挑一个毁灭,则可以用线段树建图。

    3.所有的OMG bazooka能销毁的目标集合之间互不相交,只能摧毁两个或者不摧毁。则由贪心策略得到摧毁最多舰船时所有的bazooka一定会被使用。

    证明:假设最优状态下有一枚bazooka x无法使用;则x所能摧毁的集合中有两个或者三个被别的武器所摧毁,一共消耗了两个或者三个;在使用x后,有武器多余出来被用来摧毁别的目标,则不使用x的最优状态不是最优状态(没有未来的未来不是我想要的未来);

    确定使用贪心后,就先把bazooka消灭的武器数量添加上,在这个节点稍微操作一下就好;

    仔(can)细(kao)思(ti)考(jie)后,得到了如下的代码:

    #include<bits/stdc++.h>
    #define N 200005
    #define inf 0x3f3f3f3f
    #define lson (rt<<1)
    #define rson (rt<<1|1)
    #define mid ((l+r)>>1)
    typedef unsigned int __Index;
    __Index tot;
    __Index id[N],Begin;
    int cnt,head[N],cur_edge[N],pre[N];
    bool vis[N];
    struct Edge{
        int v,cap,next;
    }edge[N];
    inline void __add(__Index a,__Index b,int c){
        edge[++cnt].v = b;
        edge[cnt].cap = c;
        edge[cnt].next = head[a];
        head[a] = cnt;
    }
    void add(__Index a,__Index b,int c){
        __add(a,b,c);
        __add(b,a,0);
    }
    void build(__Index l,__Index r,__Index rt){
        id[rt]=++tot;
        if(l==r){
            add(id[rt],l,1);
            return;
        }
        build(l,mid,lson);
        build(mid+1,r,rson);
        add(id[rt],id[lson],inf);
        add(id[rt],id[rson],inf);
    }
    void upDate(__Index L,__Index R,__Index l,__Index r,__Index rt) {
        if (L <= l and r <= R) {
            add(tot, id[rt], 1);
            return;
        }
        if (R <= mid)upDate(L, R, l, mid, lson);
        else if (L > mid)upDate(L, R, mid + 1, r, rson);
        else {
            upDate(L, mid, l, mid, lson);
            upDate(mid+1,R,mid+1,r,rson);
        }
    }
    __Index _n,m,src,dst,n;
    int d[N],numd[N];
    using namespace std;
    void Bfs(int sink){
        memset(numd,0,sizeof(numd));
        fill(d+1,d+1+n,n);
        numd[n] = n;
        d[sink] = 0;
        --numd[n],++numd[0];
        queue<int>Q;
        Q.push(sink);
        while(!Q.empty()){
            int v = Q.front();
            Q.pop();
            for(int i = head[v] ,u; ~i ; i = edge[i].next){
                u = edge[i].v;
                if(d[u] < n )continue;
                d[u] = d[v]+1;
                --numd[n];
                ++numd[d[u]];
                Q.push(u);
            }
        }
    }
    int SAP(__Index source,__Index sink){
        memcpy(cur_edge,head,(n+1)*sizeof(int));
        int max_flow = 0;
        Bfs(sink);
        int u = source,neck = 0;
        while (d[source] < n){
            if(u==sink){
                int cur_flow = inf;
                for(int from = source ; from!=sink;from = edge[cur_edge[from]].v){
                    if(cur_flow>edge[cur_edge[from]].cap){
                        neck = (__Index)from;
                        cur_flow = edge[cur_edge[from]].cap;
                    }
                }
                for(int from=source; from!=sink; from=edge[cur_edge[from]].v){
                    int tmp=cur_edge[from];
                    edge[tmp].cap-=cur_flow;
                    edge[tmp^1].cap+=cur_flow;
                }
                max_flow+=cur_flow;//累加计算最大流
                u=neck;
            }
            int i;
            for(i = cur_edge[u] ; ~i ; i = edge[i].next){
                if(edge[i].cap and d[u] == d[edge[i].v]+1)break;
            }
            if(-1!=i){
                cur_edge[u] = i;
                pre[edge[i].v] = u;
                u = edge[i].v;
            }
            else{
                --numd[d[u]];
                if(!numd[d[u]])break;
                cur_edge[u] = head[u];
                int tmp = n;
                for(int j = head[u] ; ~j ; j = edge[j].next){
                    if(edge[j].cap and tmp > d[edge[j].v]){
                        tmp = d[edge[j].v];
                    }
                }
                d[u] = tmp+1;
                numd[d[u]]++;
                if(u!=source)u = pre[u];
            }
        }
        return max_flow;
    }
    
    void init(){
        memset(head,-1, sizeof(head));
        tot = m;
        cnt = -1;
        src = ++tot;
        build(1,m,1);
        Begin = tot;
    }
    int tmp = 0;
    map<int,int>mp[N];
    void Query(int p){
        if( p > Begin){
            tmp = p-Begin;
            return;
        }
        auto it = mp[p].begin();
        Query(it->first);
        --it->second;
        if(!it->second)mp[p].erase(it);
    }
    int main(){
        ios::sync_with_stdio(false);
        cin>>_n>>m;
        init();
        int k,op,ans = 0;
        __Index sp,l,r,c;
        for(int i = 0 ; i < _n ; ++i){
            ++tot;
            cin>>op;
            switch (op){
                case 0:
                    cin>>k;
                    while (k--){
                        cin>>sp;
                        add(tot,sp,1);
                    }
                    add(src,tot,1);
                    break;
                case 1:
                    cin>>l>>r;
                    upDate(l,r,1,m,1);
                    add(src,tot,1);
                    break;
                default:
                    cin>>l>>r>>c;
                    add(tot,l,0);
                    edge[cnt].cap = 1;
                    add(tot,r,0);
                    edge[cnt].cap = 1;
                    add(tot,c,1);
                    vis[l] = vis[r] = true;
                    ans+=2;
                    break;
            }
        }
        dst = ++tot;
        for(__Index i = 1 ; i <= m ; ++i){
            if(!vis[i])add(i,dst,1);
        }
        n = tot;
        ans+=SAP(src,dst);
        for(int i=1;i<=tot;++i){
            for(int j = head[i] ; ~j  ; j = edge[j].next){
                if((j&1)and edge[j].cap){
                    mp[i][edge[j].v] = edge[j].cap;
                }
            }
        }
        cout<<ans<<"
    ";
        for(int i = 1 ; i <=  m ; ++i){
            bool f = true;
            for(int j = head[i] ; (~j) and f ; j = edge[j].next){
                if(edge[j].v == dst and edge[j].cap==1)f = false;
            }
            if(f){
                Query(i);
                cout<<tmp<<" "<<i<<"
    ";
            }
        }
    }
  • 相关阅读:
    ps -aux --sort -rss |head 列出进程拿物理内存占用排序 使用ps aux 查看系统进程时,第六列即 RSS列显示的就是进程使用的物理内存。
    13 memcache服务检查
    shell 颜色
    expr判断整数是相加的值,返回命令的返回值$? 是0,但是少数情况是1,例如1 + -1 ,$? 的结果是1 ,判断要大于1最准确
    ZABBIX监控原理
    ansible分发密钥
    再来一个expect脚本
    11:菜单自动化软件部署经典案例
    19:批量检查多个网站地址是否正常
    数组迭代
  • 原文地址:https://www.cnblogs.com/DevilInChina/p/9856219.html
Copyright © 2011-2022 走看看