这个题很清真
就是可以考虑将删除的边倒叙插入,因为题面中说了,保证删了所有边之后,保证图的连通性 ,所以先在删完点的图上缩点,然后剩下的边就是关键边,之后再把删除的边插入,这样就会使得之前的一些点之间的关键边的不关键,之后用线段树维护就行了
1 #include <set> 2 #include <cmath> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <cstring> 6 #include <iostream> 7 #include <algorithm> 8 # define maxM 100010 9 # define maxn 30010 10 # define MP make_pair 11 # define X first 12 # define Y second 13 using namespace std; 14 void ot(){cout<<"***"<<endl;} 15 void fen(){cout<<"-------------"<<endl;} 16 typedef pair<int,int> Pi; 17 int n,m; 18 struct LINK{ 19 struct node{ 20 int u,v,nxt; 21 }g[2*maxM]; 22 int adj[maxn],e; 23 void add(int u,int v){ 24 g[e]=(node){u,v,adj[u]}; 25 adj[u]=e++; 26 } 27 LINK(){memset(adj,-1,sizeof(adj)); e=0;} 28 }A,B; 29 Pi bi[maxM]; 30 bool cmp(const Pi a,const Pi b){ 31 if(a.X==b.X) return a.Y<b.Y; 32 return a.X<b.X; 33 } 34 struct QQ{ 35 int od,u,v,ans; 36 }Q[maxM]; 37 int tip; 38 void init(){ 39 scanf("%d%d",&n,&m); 40 for(int i=1;i<=m;i++){ 41 scanf("%d%d",&bi[i].X,&bi[i].Y); 42 if(bi[i].X>bi[i].Y) swap(bi[i].X,bi[i].Y); 43 // cout<<bi[i].X<<" "<<bi[i].Y<<endl; 44 } 45 // ot(); exit(0); 46 sort(bi+1,bi+m+1,cmp); 47 int x,y,z; 48 while(1){ 49 scanf("%d",&x); if(x==-1) break; 50 Q[++tip].od=x; scanf("%d%d",&Q[tip].u,&Q[tip].v); 51 if(Q[tip].u>Q[tip].v) swap(Q[tip].u,Q[tip].v); 52 // cout<<"x=="<<x<<" "<<Q[tip].u<<" "<<Q[tip].v<<endl; 53 } 54 } 55 bool operator < (const Pi a,const Pi b){ 56 if(a.X==b.X) return a.Y<b.Y; 57 return a.X<b.X; 58 } 59 bool pd[maxM]; 60 void Del_lk(){ 61 int pos; 62 for(int i=1;i<=tip;i++){ 63 if(Q[i].od) continue; 64 pos=lower_bound(bi+1,bi+m+1,MP(Q[i].u,Q[i].v) )-bi; 65 pd[pos]=1; 66 } 67 for(int i=1;i<=m;i++){ 68 if(pd[i]) continue; 69 A.add(bi[i].X,bi[i].Y); A.add(bi[i].Y,bi[i].X); 70 } 71 } 72 int dfn[maxn],low[maxn],stack[maxn],belong[maxn],cnt,stp,head; 73 bool instack[maxn]; 74 void tarjan(int x,int fa){ 75 dfn[x]=low[x]=++stp; stack[++head]=x; instack[x]=1; 76 for(int i=A.adj[x];i!=-1;i=A.g[i].nxt){ 77 int v=A.g[i].v; if(v==fa) continue; 78 if(dfn[v]==-1){ 79 tarjan(v,x); low[x]=min(low[x],low[v]); 80 } 81 else if(instack[v]) low[x]=min(low[x],dfn[v]); 82 } 83 if(low[x]==dfn[x]){ 84 int tmp; cnt++; 85 while(1){ 86 tmp=stack[head--]; 87 instack[tmp]=0; 88 belong[tmp]=cnt; 89 if(x==tmp) break; 90 } 91 } 92 } 93 int fa[maxn],dep[maxn],size[maxn],son[maxn]; 94 void dfs1(int x){ 95 size[x]=1; 96 for(int i=B.adj[x];i!=-1;i=B.g[i].nxt){ 97 int v=B.g[i].v; if(v==fa[x]) continue; 98 dep[v]=dep[x]+1; fa[v]=x; 99 dfs1(v); 100 size[x]+=size[v]; 101 if(size[son[x]] < size[v]) son[x]=v; 102 } 103 } 104 int top[maxn],id[maxn],Pos[maxn]; 105 void dfs2(int x,int tp){ 106 top[x]=tp; Pos[x]=++stp; id[stp]=x; 107 if(son[x]) dfs2(son[x],tp); 108 for(int i=B.adj[x];i!=-1;i=B.g[i].nxt){ 109 int v=B.g[i].v; if(v==fa[x] || v==son[x]) continue; 110 dfs2(v,v); 111 } 112 } 113 int sum[4*maxn],mk[4*maxn]; 114 void pushup(int now){ 115 sum[now]=sum[now<<1]+sum[now<<1|1]; 116 } 117 void pushdown(int now,int l,int r,int mid){ 118 if(mk[now]==-1) return; 119 int ls=now<<1,rs=now<<1|1; 120 sum[ls]=mk[now]*(mid-l+1); mk[ls]=mk[now]; 121 sum[rs]=mk[now]*(r-mid); mk[rs]=mk[now]; 122 mk[now]=-1; 123 } 124 void upd(int left,int right,int now,int l,int r,int num){ 125 if(left<=l && r<=right){ 126 sum[now]=num*(r-l+1); mk[now]=num; return; 127 } 128 int mid=(l+r)>>1; 129 pushdown(now,l,r,mid); 130 if(left<=mid) upd(left,right,now<<1,l,mid,num); 131 if(right>mid) upd(left,right,now<<1|1,mid+1,r,num); 132 pushup(now); 133 } 134 int query(int left,int right,int now,int l,int r){ 135 if(left<=l && r<=right) return sum[now]; 136 int mid=(l+r)>>1; 137 pushdown(now,l,r,mid); 138 int ret=0; 139 if(left<=mid) ret+=query(left,right,now<<1,l,mid); 140 if(right>mid) ret+=query(left,right,now<<1|1,mid+1,r); 141 return ret; 142 } 143 void change(int x,int y){ 144 int tx=top[x],ty=top[y]; 145 int ret=0; 146 while(tx^ty){ 147 if(dep[tx]<dep[ty]) swap(tx,ty),swap(x,y); 148 upd(Pos[tx],Pos[x],1,1,stp,0); 149 x=fa[tx]; tx=top[x]; 150 } 151 if(dep[x]>dep[y]) swap(x,y); 152 if(Pos[y]>Pos[x]) upd(Pos[x]+1,Pos[y],1,1,stp,0); 153 } 154 int find(int x,int y){ 155 int tx=top[x],ty=top[y]; 156 int ret=0; 157 while(tx^ty){ 158 if(dep[tx]<dep[ty]) swap(tx,ty),swap(x,y); 159 ret+=query(Pos[tx],Pos[x],1,1,stp); 160 x=fa[tx]; tx=top[x]; 161 } 162 if(dep[x]>dep[y]) swap(x,y); 163 if(Pos[y]>Pos[x]) ret+=query(Pos[x]+1,Pos[y],1,1,stp); 164 return ret; 165 } 166 void check1(){ 167 for(int i=1;i<=n;i++){ 168 cout<<"i= "<<i<<" "<<belong[i]<<endl; 169 } cout<<endl; 170 // cout<<cnt<<" "<<stp<<endl; 171 for(int i=1;i<=cnt;i++){ 172 cout<<"i= "<<i<<" "<<dep[i]<<" "<<fa[i]<<" "<<Pos[i]<<endl; 173 } 174 } 175 void work(){ 176 memset(dfn,-1,sizeof(dfn)); 177 memset(mk,-1,sizeof(mk)); 178 tarjan(1,-1); 179 for(int i=0;i<A.e;i++){ 180 int u=A.g[i].u, v=A.g[i].v; 181 if(belong[u]!=belong[v]){ 182 B.add(belong[u],belong[v]); 183 } 184 } 185 stp=0; 186 dfs1(1); dfs2(1,1); 187 // check1(); 188 upd(2,stp,1,1,stp,1); 189 for(int i=tip;i>=1;i--){ 190 // cout<<"i=="<<i<<endl; 191 if(Q[i].od){ 192 if(belong[Q[i].u]==belong[Q[i].v]){ 193 Q[i].ans=0; continue; 194 } 195 // cout<<belong[Q[i].u]<<" "<<belong[Q[i].v]<<endl; 196 Q[i].ans=find(belong[Q[i].u],belong[Q[i].v]); 197 } 198 else{ 199 if(belong[Q[i].u]==belong[Q[i].v]) continue; 200 change(belong[Q[i].u],belong[Q[i].v]); 201 } 202 } 203 for(int i=1;i<=tip;i++){ 204 if(!Q[i].od) continue; 205 printf("%d ",Q[i].ans); 206 } 207 } 208 int main(){ 209 // freopen("a.in","r",stdin); 210 init(); 211 Del_lk(); 212 work(); 213 }