节点,边构成了图
通过邻接数组存储边集。
题意可知 ,更新会将自己的主链转发出去。
而更新有两种情况
1.添加一个新块
2.邻居传过来的主链,如果符合题目中的要求,则进行更新
重点就是如何进行更新。
可以构造一个结构体,包含到达日期,发送的主链,以及发送的对象
发送的对象是个数组比较好,这样一次转发只需要拷贝一次主链就可以了。
开始的时候80分,时间超时,改成这样后就100分,1.8s过了。
至于怎么存储这些需要更新的链,我用的multiset(因为如果根据截止日期排序,set的话会把截止日期相同的节点视作同一个节点,然后不予添加),根据截止日期进行排序
现在想想,其实链表就行,根本没必要通过set,因为是有序的。
还有一点要注意,就是题目中的bi可能跨度比较大,两个相邻的bi之间隔了很长时间,我们需要每隔一个时间单位统一接收一次可以接收的全部主链。
代码如下
#include<iostream>
#include<vector>
#include<string>
#include<map>
#include<set>
#include<queue>
#include<algorithm>
#include<cstdio>
#include<sstream>
#include<list>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pa;
int n,m;
int t,k;
vector<int> gra[505];
vector<int> ls[505];//链
struct unit{
int ddl;//到达的时间
vector<int> mlist;//发送的主链
vector<int> to;
bool operator <(const unit&t)const{
return ddl<t.ddl;
}
};
multiset<unit> upd;
int curtime=0;
void init()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
ls[i].push_back(0);
for(int i=1;i<=m;i++){
int from,to;
cin>>from>>to;
gra[from].push_back(to);
gra[to].push_back(from);
}
cin>>t>>k;
getchar();
}
void send(int a,int b);
void recv(int b)//当前时间
{
while(1){
auto it=upd.begin();
if(!upd.empty()&&it->ddl<=b){//比较,然后接收
for(auto to:it->to){
if(ls[to].size()<it->mlist.size())
{ls[to]=it->mlist;
send(to,b);
}
else if(ls[to].size()==it->mlist.size()){
if(it->mlist.back()<ls[to].back())
{ls[to]=it->mlist;
send(to,b);
}
}
}
upd.erase(it);
}
else break;
}
}
void send(int a,int b)//当前时间
{
unit temp;
temp.ddl=b+t;
temp.mlist=ls[a];
for(auto to:gra[a])
temp.to.push_back(to);
upd.insert(temp);
}
void create(int a,int b,int c)
{
ls[a].push_back(c);
send(a,b);
}
int main()
{
while(k--){
string str;
getline(cin,str);
istringstream ss(str);
int tmp;
vector<int> temv;
while(ss>>tmp)temv.push_back(tmp);
int a,b,c;
a=temv[0],b=temv[1];
if(curtime!=b){
for(int i=curtime;i<=b;i++)
recv(i);
curtime=b;
}
if(temv.size()==2){
cout<<ls[a].size();
for(auto &tmp:ls[a])
cout<<" "<<tmp;
cout<<"\n";
}
else{
c=temv[2];
create(a,b,c);
}
}
}