题解 P1160 【队列安排】
第一篇题解,啊,蒟蒻的我无比激动;
------------咳咳------------
说实话,写这道题是因为我们老师明天要考该类型,然后临时抱佛脚。。。
------------咳咳------------
好了说正事,这个是一个链式结构,确实也是线性,我们大家可以想象一下一个链子,一块一块连起来,是头挨头尾接尾
(这个说法好zz)
反正大家想象一下就好(我的物理老师告诉我做题都是要情景想象)
好的,大家都想象好了,然后我们就引进两个数组head[],next[]; 顾名思义,它就是头和尾的意思。思考一下,怎么连接呢?
大家可以查一下有一个叫 前向星 和 链式前向星 (ssfz神牛Malash最强),重点就是链式前向星,大家一定要看。
然后就有了这个
if(!p){ //放在左边
next[head[k]]=i;//断开链子并接上
head[i]=head[k];//将我们上一步完善
next[i]=k;// 连接下一个
head[k]=i;//将下一个的head连在i上
}else{//放在右边,而且具有对称性,比较容易来修改代码
head[next[k]]=i;
next[i]=next[k];
head[i]=k;
next[k]=i;//由于同理,就不再解释了
}
大家可以手动模拟一下咯,受到链式前向星的启发就有了它;
0 1 2 3 4
head / 4 0 2 3 next 2 0 3 4 1
作为一个良心讲题人,上面是我模拟的(有错请指出,我没在纸上写)
再模拟几遍大家就应该知道了;
删去了话,其实也可以用链式的常规操作,但是我太懒,而数据又不是太大,所以开了个桶,操作简单。
再附上蒟蒻的代码
#include<bits/stdc++.h>//万能头 大家都在用吧
using namespace std;
int n,tong[100007],m;//桶删数
int head[100007],next[100007];//链式常规操作
int main(){
scanf("%d",&n);
next[0]=1;//将0的下一个定为1
for(int i=2,p,k;i<=n;i++){
scanf("%d%d",&k,&p);
if(!p){ //放在左边
next[head[k]]=i;//断开链子并接上
head[i]=head[k];//将我们上一步完善
next[i]=k;// 连接下一个
head[k]=i;//将下一个的head连在i上
}else{//放在右边,而且具有对称性,比较容易来修改代码
head[next[k]]=i;
next[i]=next[k];
head[i]=k;
next[k]=i;//由于同理,就不再解释了
}
}
scanf("%d",&m);
for(int i=1,t;i<=m;i++){
scanf("%d",&t);
tong[t]=1;//tong删法
}
for(int i=next[0];1;i=next[i]){
if(!tong[i]) printf("%d ",i);
if(!next[i]) break;/*为甚要放在后面而不是for循环上,
大家可以试试,这样应该就能明白了 */
}
}
(呼,第一篇题解,好虚好虚)
这样大家就可以了解链式结构了 最后附上链式前向星,(板子可能不好,仅供参考)
void add(int a,int b,int w){
edge[++cent].next=head[a];
edge[cent].to=b;
edge[cent].w=w;
head[a]=cent;
}
有什么错误,请各位大佬指出,我会第一时间改的(`・ω・´)