• 航线规划


    命运女神终于眷顾了我!!!

    这两天我打费用流、旋转卡壳不是WA就是莫名TLE,这道我敬而远之的题居然一遍AC!!!


     进入正题。

    考虑到条件:任何时候可以互达,知道它永远联通。

    真理:加边永远比删边好做,于是很自然的想到离线。

    做法:1.在所有剩余的边中找出一棵生成树。

          2.将剩余的却不在生成树内的边加上。

       3.反着输入统计答案或加边。

          4.倒叙输出答案,完结撒花。

    就是这么easy。。。。。。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e6;
    int n,m;
    int beg[maxn],nex[maxn],to[maxn],e;
    inline void add(int x,int y){
        e++;nex[e]=beg[x];
        beg[x]=e;to[e]=y;
    }
    struct node{
        int x,y,flag;
    }a[maxn],q[maxn];
    int fa[maxn];
    map<pair<int,int>,int>rev;
    int find(int x){
        if(x==fa[x])return x;
        return fa[x]=find(fa[x]);
    }
    int son[maxn],size[maxn],dep[maxn],f[maxn];
    inline void dfs1(int x,int anc){
        dep[x]=dep[anc]+1;
        size[x]=1;
        f[x]=anc;
        for(int i=beg[x];i;i=nex[i]){
            int t=to[i];
            if(t==anc)continue;
            dfs1(t,x);
            size[x]+=size[t];
            if(size[t]>size[son[x]])
                son[x]=t;
        }
    }
    int id[maxn],cnt,top[maxn];
    inline void dfs2(int x,int topc){
        id[x]=++cnt;
        top[x]=topc;
        if(!son[x])return;
        dfs2(son[x],topc);
        for(int i=beg[x];i;i=nex[i]){
            int t=to[i];
            if(t==f[x]||t==son[x])
                continue;
            dfs2(t,t); 
        }
    }
    int tr[maxn],lazy[maxn];
    inline void build(int h,int l,int r){
        tr[h]=r-l+1;
        if(l==r)return;
        int mid=(l+r)>>1;
        build(h<<1,l,mid);
        build(h<<1|1,mid+1,r);
    }
    inline void pushup(int h){
        tr[h]=0;
        lazy[h]=1;
    }
    inline void pushdown(int h){
        if(!lazy[h])return;
        pushup(h<<1);
        pushup(h<<1|1);
        lazy[h]=0;
    }
    inline void modify(int h,int l,int r,int x,int y){
        if(l>y||r<x)return;
        if(tr[h]==0)return;
        if(l>=x&&r<=y){
            //pushup(h);
            tr[h]=0;
            return;
        }
        //pushdown(h);
        int mid=(l+r)>>1;
        modify(h<<1,l,mid,x,y);
        modify(h<<1|1,mid+1,r,x,y);
        tr[h]=tr[h<<1]+tr[h<<1|1];
    }
    inline void mc(int x,int y){
        while(top[x]!=top[y]){
            if(dep[top[x]]<dep[top[y]])swap(x,y);
            modify(1,1,n,id[top[x]],id[x]);
            x=f[top[x]];
        }
        if(dep[x]>dep[y])swap(x,y);
        if(x==y)return;
        modify(1,1,n,id[x]+1,id[y]);
    }
    inline int query(int h,int l,int r,int x,int y){
        if(l>y||r<x)return 0;
        if(tr[h]==0)return 0;
        if(l>=x&&r<=y)return tr[h];
        int mid=(l+r)>>1;
        return query(h<<1,l,mid,x,y)+query(h<<1|1,mid+1,r,x,y);
    }
    inline int qc(int x,int y){
        int ans=0;
        while(top[x]!=top[y]){
            if(dep[top[x]]<dep[top[y]])swap(x,y);
            ans+=query(1,1,n,id[top[x]],id[x]);
            x=f[top[x]]; 
        }
        if(dep[x]>dep[y])swap(x,y);
        if(x==y)return ans;
        ans+=query(1,1,n,id[x]+1,id[y]);
        return ans;
    }
    int num,ans[maxn],tot;
    int main(){
        cin>>n>>m;
        for(int i=1;i<=m;i++){
            scanf("%d%d",&a[i].x,&a[i].y);
            a[i].flag=1;
            rev[make_pair(a[i].x,a[i].y)]=i;
            rev[make_pair(a[i].y,a[i].x)]=i;
        }
        int opt,x,y;
        while(1){
            scanf("%d",&opt);
            if(opt==-1)break;
            scanf("%d%d",&x,&y);
            if(!opt)a[rev[make_pair(x,y)]].flag=0;
            q[++num]=(node){x,y,opt};
        }
        for(int i=1;i<=n;i++)
            fa[i]=i;
        int cnt=0;
        for(int i=1;i<=m;i++){
            if(a[i].flag==0)continue;
            if(find(a[i].x)!=find(a[i].y)){
                fa[find(a[i].x)]=find(a[i].y);
                add(a[i].x,a[i].y);
                add(a[i].y,a[i].x);
                a[i].flag=0;
            }
        }
        dfs1(1,0);
        dfs2(1,1);
        build(1,1,n);
        modify(1,1,n,1,1);
        for(int i=1;i<=m;i++){
            if(!a[i].flag)continue;
            mc(a[i].x,a[i].y);
        }
        for(int i=num;i;i--){
            if(q[i].flag)ans[++tot]=qc(q[i].x,q[i].y);
            else mc(q[i].x,q[i].y);
        }
        for(int i=tot;i;i--)
            printf("%d
    ",ans[i]);
        return 0;
    }

    深深地感到自己的弱小。

  • 相关阅读:
    Math 和 Date
    GRID布局
    移动端项目布局类型
    媒体查询 + rem用法
    字符串
    ES5 中常见的数组常用方法
    数组的排序
    毕设制作:前端界面 2020-02-01
    阅读笔记十六——排序算法
    阅读笔记十五——阿里面试题
  • 原文地址:https://www.cnblogs.com/syzf2222/p/12375505.html
Copyright © 2020-2023  润新知