题目描述
题目大意
有n个点,每个点的编号为i。有3种,一共m个操作:
1)将y连到x的后面(保证x后面和y前面没有连点)
2)将x-y的连接断开(保证一定存在x-y的连接)
3)输出x所在的链(按顺序输出)
题目分析
设pre[x] //记录x的前驱节点,ne[x] //记录x的后继节点
这样我们连接/断开边时都只需要操作pre[]和ne[]数组即可。
输出x所在的链也只需要顺着链表往前和往后遍历即可。
代码如下
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <algorithm>
#include <iomanip>
#define LL long long
#define ULL unsigned long long
#define PII pair<int,int>
#define PLL pair<LL,LL>
#define PDD pair<double,double>
#define x first
#define y second
using namespace std;
const int N=2e5+5,mod=998244353;
int pre[N],ne[N];
void print(int x) //输出x所在的链
{
int p=x;
vector<int> st,ans;
while(pre[p]!=p) //从x开始往前遍历
{
st.push_back(pre[p]);
p=pre[p];
}
for(int i=st.size()-1;i>=0;i--) ans.push_back(st[i]); //将栈中的节点放入ans
ans.push_back(x);
p=x;
while(ne[p]!=p) //从x开始往后遍历
{
ans.push_back(ne[p]);
p=ne[p];
}
printf("%d ",ans.size()); //输出答案
for(int it:ans) printf("%d ",it);
puts("");
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) pre[i]=ne[i]=i; //初始化
while(m--)
{
int op,x,y;
scanf("%d",&op);
if(op==1)
{
scanf("%d%d",&x,&y); //连接x,y
pre[y]=x; //让y的前驱等于x
ne[x]=y; //让x的后继等于y
}
else if(op==2)
{
scanf("%d%d",&x,&y); //断开下x,y
pre[y]=y; //让y没有前驱
ne[x]=x; //让x没有后继
}
else
{
scanf("%d",&x);
print(x);
}
}
return 0;
}