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;
}