2 条题解
-
0
#include<bits/stdc++.h> using namespace std; const int N=1e6+10, inf=1e9; int a[N], b[N], dep[N], fa[N], del[N], id[N], tsp, dfn[N]; int siz[N], n, m; vector<int> G[N]; int findfa(int x) {return (fa[x]==x)? fa[x]: fa[x]=findfa(fa[x]);} bool pd1(int x, int y){ int tx=findfa(x), ty=findfa(y); if(tx!=ty) {fa[tx]=ty; return 0;} else return 1; } void dfs(int x){ dfn[x]=++tsp; siz[x]=1; for(int y: G[x]){ dep[y]=dep[x]+1; id[y]=id[x]; dfs(y); siz[x]+=siz[y]; } } bool pd2(int x, int y){ return ((dfn[x]>=dfn[y]) && (dfn[x]<=dfn[y]+siz[y]-1)); //x在y的子树内 } int query(int x, int y){ if(x==y) return 0; if(id[x]!=id[y]) return inf; int res=inf; if(pd2(x, y)) res=min(res, dep[x]-dep[y]); //x是y的子节点 if(pd2(del[id[y]], y)) res=min(res, dep[del[id[y]]]-dep[y]+dep[x]+1); //通过那条断的边走到环上的y,答案为环上的路径加x到环上那个节点的路径加短边 return res; } bool check(int x){ int i, w; for(i=1, w=1; i<=n, w<=m;){ if(query(a[i], w)<=x) i++; else w++; } return i>n; } int main(){ freopen("a.in", "r", stdin); int T; scanf("%d", &T); while(T--){ scanf("%d%d", &n, &m); for(int i=1; i<=m; i++){ G[i].clear(); dep[i]=0; fa[i]=i; del[i]=0; id[i]=0; del[0]=0; dfn[i]=0; } for(int i=1; i<=n; i++) scanf("%d", &a[i]); for(int i=1; i<=m; i++){ scanf("%d", &b[i]); if(pd1(b[i], i)==0) G[b[i]].push_back(i); else del[i]=b[i]; //有环,断这条边 } tsp=0; for(int i=1; i<=m; i++) if(del[i]) id[i]=i, dfs(i); int l=0, r=m, p=-1; while(l<=r){ int mid=(l+r)/2; if(check(mid)) r=mid-1, p=mid; else l=mid+1; } printf("%d\n", p); } return 0; } -
0
#include<bits/stdc++.h> using namespace std; const int N=1e6+10, inf=1e9; int a[N], b[N], dep[N], fa[N], del[N], id[N], tsp, dfn[N]; int siz[N], n, m; vector<int> G[N]; int findfa(int x) {return (fa[x]==x)? fa[x]: fa[x]=findfa(fa[x]);} bool pd1(int x, int y){ int tx=findfa(x), ty=findfa(y); if(tx!=ty) {fa[tx]=ty; return 0;} else return 1; } void dfs(int x){ dfn[x]=++tsp; siz[x]=1; for(int y: G[x]){ dep[y]=dep[x]+1; id[y]=id[x]; dfs(y); siz[x]+=siz[y]; } } bool pd2(int x, int y){ return ((dfn[x]>=dfn[y]) && (dfn[x]<=dfn[y]+siz[y]-1)); //x在y的子树内 } int query(int x, int y){ if(x==y) return 0; if(id[x]!=id[y]) return inf; int res=inf; if(pd2(x, y)) res=min(res, dep[x]-dep[y]); //x是y的子节点 if(pd2(del[id[y]], y)) res=min(res, dep[del[id[y]]]-dep[y]+dep[x]+1); //通过那条断的边走到环上的y,答案为环上的路径加x到环上那个节点的路径加短边 return res; } bool check(int x){ int i, w; for(i=1, w=1; i<=n, w<=m;){ if(query(a[i], w)<=x) i++; else w++; } return i>n; } int main(){ freopen("a.in", "r", stdin); int T; scanf("%d", &T); while(T--){ scanf("%d%d", &n, &m); for(int i=1; i<=m; i++){ G[i].clear(); dep[i]=0; fa[i]=i; del[i]=0; id[i]=0; del[0]=0; dfn[i]=0; } for(int i=1; i<=n; i++) scanf("%d", &a[i]); for(int i=1; i<=m; i++){ scanf("%d", &b[i]); if(pd1(b[i], i)==0) G[b[i]].push_back(i); else del[i]=b[i]; //有环,断这条边 } tsp=0; for(int i=1; i<=m; i++) if(del[i]) id[i]=i, dfs(i); int l=0, r=m, p=-1; while(l<=r){ int mid=(l+r)/2; if(check(mid)) r=mid-1, p=mid; else l=mid+1; } printf("%d\n", p); } return 0; }
- 1
信息
- ID
- 2120
- 时间
- 4000ms
- 内存
- 512MiB
- 难度
- 10
- 标签
- 递交数
- 6
- 已通过
- 4
- 上传者