洛谷 P1653 猴子
题目:猴子
思路:
QAQ……
当时想的就是……反着处理,把删边看做加边。
最开始把要删的边先删除,然后dfs一遍把联通块处理一下,用类似缩点的方法缩一下。
然后搞一个带权并查集。
注意一定要建图啊……不要直接用两只手拉的猴子处理,会很麻烦
代码:
#include<bits/stdc++.h>
using namespace std;
#define maxn 400000
#define read(x) scanf("%d",&x)
int n,m;
int lson[maxn+5],rson[maxn+5];
int lson1[maxn+5],rson1[maxn+5];
vector<int> g[maxn+5];
int a[maxn+5],b[maxn+5];
int vis[maxn+5],cnt;
int fa[maxn+5];
int t[maxn+5];
int find(int x) {
if(fa[x]) {
int y=fa[x];
fa[x]=find(fa[x]);
if(t[x]==-1) t[x]=t[y];
return fa[x];
}
else return x;
}
void dfs(int x,int y) {
vis[x]=y;
for(int i=0; i<g[x].size(); i++) {
int h=g[x][i];
if(!vis[g[x][i]]) dfs(h,y);
}
}
int main() {
read(n),read(m);
for(int i=1; i<=n; i++) {
read(lson[i]),read(rson[i]);
lson1[i]=lson[i],rson1[i]=rson[i];
}
for(int i=1; i<=m; i++) {
read(a[i]),read(b[i]);
if(b[i]==1) b[i]=lson1[a[i]],lson[a[i]]=-1;
else b[i]=rson1[a[i]],rson[a[i]]=-1;
}
for(int i=1; i<=n; i++) {
if(~lson[i]) g[i].push_back(lson[i]),g[lson[i]].push_back(i);
if(~rson[i]) g[i].push_back(rson[i]),g[rson[i]].push_back(i);
}
for(int i=1; i<=n; i++) {
if(!vis[i]) dfs(i,++cnt);
}
memset(t,-1,sizeof(t));
for(int i=m; i>=1; i--) {
int fa1=find(vis[a[i]]),fa2=find(vis[b[i]]);
if(fa1==fa2) continue;
if(fa1==1) fa[fa2]=fa1;
else fa[fa1]=fa2;
if(fa1==1) {
if(t[fa2]==-1) {
t[fa2]=i-1;
}
}
if(fa2==1) {
if(t[fa1]==-1) {
t[fa1]=i-1;
}
}
}
for(int i=1; i<=n; i++) {
find(i);
if(vis[i]==1) printf("-1\n");
else printf("%d\n",t[vis[i]]);
}
return 0;
}