航线规划
命运女神终于眷顾了我!!!
这两天我打费用流、旋转卡壳不是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\n",ans[i]); return 0; }
深深地感到自己的弱小。