题意:有n个栈,第i个栈刚开始只放了i,有m个操作,每次把ai放到bi里,求最后每个栈里元素的个数和元素
模拟肯会超时,那么我们就想用双链表来写
s数组用来存一个数的前面相连的数或者后面的数(因为堆的话一个数只能连两个数)
- struct name{
- int pre,next;
- }s[N];
sta数组用来记录栈顶和栈底元素
- struct po{
- int top,bot;
- }sta[N];
f数组来记录这个数输出过没有,num来记录每个栈的元素的个数
int f[N],num[N];
刚开始初始化的时候每个栈的栈顶和栈底都是i本身,然后num都是1,f初始化为0,每个数没有与他相连的数,所以前面后面都是0
- for(int i=1;i<=n;i++){
- num[i]=1;
- sta[i].top =sta[i].bot =i;
- f[i]=0;
- s[i].next =s[i].pre =0;
- }
然后我们对于把a这个栈放到b这个栈的add操作:
我们分别用xyzq来记录a的栈顶和栈底,b的栈顶和栈底
把a放入b,那么a的栈底就是b的栈顶
a的num要加到b的num里去,a的num变成0
然后a的栈顶x就会连上b的栈顶z,判断一下x有没有与他相连的数
如果没有就把z连到x的后面next,如果有就连到x的前面pre
z的情况也是一样,如果z后面没有的话就连到后面,有的话就连到前面
- #include<iostream>
- #include<algorithm>
- #include<cmath>
- #include<stack>
- #include<vector>
- #include<queue>
- #include<set>
- #include<cstring>
- #include<list>
- #include<map>
- #include<cstdio>
- typedef long long ll;
- typedef int64_t s64;
- using namespace std;
- struct node{
- int pre,next;
- }s[200005];
- struct stac{
- int top,bot;
- }sta[200005];
- int num[200005];
- void add(int a,int b){
- int x=sta[a].top;
- int y=sta[a].bot;
- int z=sta[b].top;
- int q=sta[b].bot;
- if(!num[b]){ //b栈中没有东西
- sta[b].bot=x; //a的头变b的底
- sta[b].top=y; //a的底比b的头
- sta[a].top=sta[a].bot=0; //把a头和底置0
- }
- else{ //b栈有东西
- if(!s[x].next){ //判断a栈中的头是否是next空(因为此题为双向链表不能确定是next还是pre)
- s[x].next=z;
- }
- else{ //判断a栈中的头是否是pre空
- s[x].pre=z;
- }
- if(!s[z].next){ //判断b栈中的头是否是next空(双向链表所以a和b是需要相互连接的)
- s[z].next=x;
- }
- else{ //判断b栈中的头是否是pre空
- s[z].pre=x;
- } //在这之前都是在做将ab栈连接起来的操作
- sta[b].top=y; //把a的底变b的头
- sta[a].top=sta[a].bot=0; //把a的头和底置0
- }
- num[b]+=num[a];
- num[a]=0;
- }
- int sig[200005];
- int main(){
- int n,m;
- while(cin>>n>>m){
- for(int i=1;i<=n;i++){ //初始化n个栈
- s[i].pre=s[i].next=0;
- sta[i].top=sta[i].bot=i;
- num[i]=1;
- sig[i]=0;
- }
- int x,y;
- while(m--){
- cin>>x>>y;
- if(num[x]==0)
- continue;
- add(x,y);
- }
- for(int i=1;i<=n;i++){
- int k=sta[i].top;
- cout<<num[i]; //输出当前栈中的数据个数
- if(num[i]){ //判断是否栈中有数据
- while(k){
- cout<<" "<<k;
- sig[k]=1; //每次找到并且输出后都需要标记
- if(s[k].next&&sig[s[k].next]!=1){ //寻找下一个数据,因不确定是next还是pre所以需要进行以下的判断
- k=s[k].next;
- }
- else if(s[k].pre&&sig[s[k].pre]!=1){
- k=s[k].pre;
- }
- else{
- k=0; //找不到下一个退出循环
- }
- }
- }
- cout<<endl;
- }
- }
- return 0;
- }