题意
当某个节点的链更新时,会将它的主链发送给它相邻的节点(邻居);而当节点收到链时,决定是否更新自己的主链。
下列情况可能会导致某个节点的链更新:
-
某个节点接收到邻居发送过来的链,与当前自己的主链进行比较:
- 如果接收到的链更长,则将其作为自己的主链:
- 如果收到的链长度与自身主链相同,且最后一块编号更小,则将其作为自己的主链
- 如果接收到的链更短,则直接忽略该链。
-
某个节点产生一个新块,将新块放在主链的尾部。
假设网络带宽足够大,每个节点状态更新后,会立刻将自己的主链同时发送给所有邻居。
现在已知整个网络的结构以及每个节点产生新块的时间,需要查询特定时刻某个节点的主链。
分析:
可以不用优先队列,直接用队列就可以实现按时间的更新,因为题目已经保证了时间一定是从小到大出现的。
每一次产生新的节点时,先更新一下此时间之间的数据即可。
C++ 代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5 ;
typedef long long ll;
#define first fi;
#define second se;
int n,m,tot,t,k,head[N];
struct Edge{
int v,next;
}edge[N];
vector<int> dat[510];
void add(int u,int v) {
edge[++tot]={v,head[u] } ;
head[u]=tot;
}
struct node{ //队列中的数据
int t,pos;
vector<int> v;
};
queue<node > q;
void update(int t,int x){ //传播向子节点
for(int i=head[x];i;i=edge[i].next) {
int v=edge[i].v;
q.push({t,v,dat[x]} );
}
}
void cal(int tt) {
while(q.size() ) {
auto x=q.front();
if(x.t<=tt) {
q.pop();
int u=x.pos;
if(x.v.size()>dat[u].size() ) {
dat[u] = x.v,update(x.t+t,u);
}
else if(x.v.size()==dat[u].size() ){
int s=dat[u].size() ;
if(dat[u][s-1]>x.v[s-1]) //编号更小
dat[u]=x.v,update(x.t+t,u) ;
}
} else break;
} return ;
}
void update(int a[] ) {
cal(a[1]);
int x=a[0];
dat[x].push_back(a[2]);
update(a[1]+t,x); //传播
return ;
}
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++) {
int u,v; cin>>u>>v;
add(u,v),add(v,u);
}
for(int i=1;i<=n;i++) dat[i].push_back(0); //init
cin>>t>>k; getchar();
for(int i=1;i<=k;i++) {
int a[4],cnt=0 ;
string str; getline(cin,str);
stringstream ss(str);
while(ss>>a[cnt]) cnt++;
if(cnt==2) {
cal(a[1]);
cout<<dat[a[0]].size()<<' ';
for(int i=0;i<dat[a[0]].size();i++)
cout<<dat[a[0]][i]<<' ';
cout<<'\n';
} else update(a);
}
return 0;
}