2021湘潭全国邀请赛 J题 Stacks

Stacks

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/262144 K (Java/Others)
Total Submission(s): 226 Accepted Submission(s): 39

Problem Description
There are N stacks, numbered from 1 to N. Initially, the i-th stack only contains a number i. Now there are M move operations, and the i-th operation is to move all the numbers in stack ai to stack bi. Specifically speaking, we pop all the numbers in stack ai one by one, and push them to stack bi in the order of popping (the first to be popped is the first to be pushed).

After all the M operations, you should output the numbers in the stacks.

Input
There are multiple test cases.

For each test case, the first line contains 2 integers N and M (1≤M≤N≤105).

In the next M lines, each line contains 2 integers ai and bi (1≤a,b≤N, a≠b), denoting an operation.

It’s guaranteed that the sum of N of all the test cases is no more than 2⋅105.

Output
For each test case, print n lines. The i-th line begins with an integer Si, denoting the number of numbers in the i-th stack, followed by Si integers, denoting the numbers in the i-th stack from top to bottom.

Sample Input
6 5
1 2
2 3
3 4
4 5
6 2

Sample Output
0
1 6
0
0
5 4 2 1 3 5
0

思路:首先感谢Rrrrya的指点 直接暴力O(n^2)超时 需要优化
优化:使用双链表(注意坑点)代码中有注释思路就在里面

#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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值