文章目录
点击前往试题目录:https://blog.csdn.net/best335/article/details/99550556
题目描述
解题思路
题意简单清晰:
- 总共不超过500个节点,编号1~n。
- 每个节点各自维护一条主链,初始时每个链的长度为1,值为0,最大长度为500。
- 节点间共有m条相互可达的无向路径。
- 更新策略:
- 主动更新:
- 输入a b c
- 被动更新:
- 相邻节点更新后经过传输延时t后
- 相邻接点主链长度更长 或者 两条链长度相同且相邻节点尾块块号更小
- 主动更新:
- 有更新延时t,不超过1000。
- 每次更新可以看做是做一次关于当前时间b+传输延时t的更新。
- 有两种操作:
- 更新主链:
- 该行格式为:a b c
- 格式解释:更新a节点在b时刻向其主链添加块号c
- 注意:|c|<109
- 查询主链:该行格式为:a b
- 格式解释:查询在b时刻a节点的主链
- 输出格式:a节点主链长度[空格]顺序输出主链块号,每个块号中间用空格相隔
- 更新主链:
仔细审题之后,发现这道题涉及一点图的BFS以及SPFA。
定义:
转折点:任意相邻两行b不同时的第二行的b为转折时间,简称转折点。
决策:
-
使用vector G[501]建立无向图
-
使用vector Links[501]维护转折点的实时主链
-
使用unordered_map<int, unordered_map<int,vector > > F
维护临时主链<时间,<节点,节点更新时的临时主链> > -
unordered_map<int, vector > tmpSearch
维护转折点前的查询队列<查询时间,查询节点队列> -
unordered_map<int, unordered_map<int, int> > tmpUpdate
维护转折点前的更新队列<更新时间,<更新节点,更新块号> > -
每次在转折点的时刻或所有输入结束时做如下操作:
- 按队列时间顺序接收和更新所有转折点之前的主链
- 处理转折点之前的查询
- 处理转折点之前的更新
博主精力有限,暂不深究未满分原因,以上解题思路希望对你们有帮助。
博主精力有限,暂不深究未满分原因,以上解题思路希望对你们有帮助。
博主精力有限,暂不深究未满分原因,以上解题思路希望对你们有帮助。
以下代码需要你静下心来阅读
70分代码
备注:代码底部有测试数据
#include<iostream>
#include<vector>
#include<map>
#include<set>
#include<unordered_map>
#include<unordered_set>
#include<string>
using namespace std;
vector<int> G[501];//图
vector<int> Links[501];//主链
set<int> Q;//更新时间点队列索引
set<int>::iterator itQ;
unordered_map<int, unordered_map<int,vector<int> > > F;//更新时间点队列
unordered_map<int, unordered_map<int,vector<int> > >::iterator itF;
int n,m,t,k,u,v,a,b,c;//题意参数
set<int> TS,TU;//TS:tempsearch查询队列索引 TU:tempUpdate更新队列索引
set<int>::iterator itTS,itTU;
unordered_map<int, vector<int> > tmpSearch;//查询队列
unordered_map<int, vector<int> >::iterator itTmpS;
unordered_map<int, unordered_map<int, int> > tmpUpdate;//更新队列
unordered_map<int, unordered_map<int, int> > ::iterator itTmpU;
void enque(const int& time,const int& point){//标记time时刻point节点将要更新
unordered_map<int, unordered_map<int,vector<int> > >::iterator it = F.find(time);
if(it == F.end()){
Q.insert(time);
unordered_map<int,vector<int> > M;
M.insert(pair<int,vector<int> >(point,vector<int>(Links[point])));
F.insert(pair<int,unordered_map<int,vector<int> > >(time,M));
}
else{
unordered_map<int, vector<int> >::iterator itM = it->second.find(point);
if (itM == it->second.end()) {
it->second.insert(pair<int, vector<int> >(point, vector<int>(Links[point])));
}
else {
const vector<int>& vM = itM->second;
int n1 = Links[point].size(), n2 = vM.size();
if (n1 > n2 || n1 == n2&&Links[point].back() < vM.back()) {
itM->second = vector<int>(Links[point]);
}
}
}
}
void receiveChain() {//接收查询或更新前的主链 这个函数有点绕
int timeQ = Q.empty() ? ::b : 0, timeT, flagQ=0, b = TS.empty()? ::b : *TS.begin();
do {
while(!TU.empty()&& (timeT = *(itTU = TU.begin())) < timeQ){//更新timeQ时间点前的主链信息 注意timeQ的取值 为了复用外围嵌套了一个do while循环
const unordered_map<int,int>& M = tmpUpdate.find(timeT)->second;
for (unordered_map<int,int>::const_iterator itM = M.begin(); itM != M.end(); ++itM){
Links[itM->first].emplace_back(itM->second);
enque(timeT + t, itM->first);
}
TU.erase(itTU);
tmpUpdate.erase(timeT);
}
if (flagQ == 1) {//如果不是第一次循环 更新邻接点主链信息
const unordered_map<int,vector<int> >& M = F.find(timeQ)->second;
for (unordered_map<int,vector<int> >::const_iterator itM = M.begin(); itM != M.end(); ++itM) {
const int& v = itM->first;
const vector<int>& link = itM->second;
for (int i = 0, ni = G[v].size(), n1, n2; i<ni; ++i) {
n1 = link.size(), n2 = Links[G[v][i]].size();
if (n1<n2 || n1 == n2&&link.back() >= Links[G[v][i]].back()) continue;
Links[G[v][i]] = link;
enque(t + timeQ, G[v][i]);
}
}
F.erase(timeQ);
Q.erase(itQ);
continue;
}
flagQ = 1;
} while (!Q.empty() && (timeQ = *(itQ = Q.begin())) <= b);
}
void outputChain() {//输出所有转折时间点之前待查询的节点
for (itTS = TS.begin(); itTS != TS.end();++itTS) {
itTmpS = tmpSearch.find(*itTS);
const vector<int>& V = itTmpS->second;
itTmpU = tmpUpdate.find(itTmpS->first);
for (int i = 0, ni = V.size(), link_length, link_value, link_flag; i<ni; ++i) {
link_length = Links[V[i]].size();
link_flag = 0;
if (itTmpU != tmpUpdate.end()) {
const unordered_map<int, int>& M = itTmpU->second;
unordered_map<int, int>::const_iterator itM = M.find(V[i]);
if (itM != M.end()) {
++link_length;
link_flag = 1;
link_value = itM->second;
}
}
cout << link_length;
for (int j = 0, nj = Links[V[i]].size(); j<nj; ++j) {
cout << ' ' << Links[V[i]][j];
}
if (link_flag == 1) {
cout << ' ' << link_value;
}
cout << endl;
}
}
tmpSearch.clear();
TS.clear();
}
void updateChain() {//更新主链
for(itTmpU=tmpUpdate.begin();itTmpU!=tmpUpdate.end();++itTmpU){
const unordered_map<int,int>& M = itTmpU->second;
const int & timeU = itTmpU->first;
for (unordered_map<int, int>::const_iterator itM = M.begin(); itM != M.end(); ++itM) {
Links[itM->first].emplace_back(itM->second);
enque(timeU + t, itM->first);
}
}
tmpUpdate.clear();
TU.clear();
}
void solve(){
receiveChain();
outputChain();
updateChain();
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cin>>n>>m;
for(int i=0;i<m;++i){
cin>>u>>v;
G[u].emplace_back(v);
G[v].emplace_back(u);
}
for (int i = n; i > 0; --i) {
Links[i].emplace_back(0);
}
cin>>t>>k;
string s;
for(int i=0,j,nj,lastTaskId=1,xk=k-1,type;i<k;++i){
cin>>a>>b,type=-1;
getline(cin,s);
//以下直到空行区域内判断该输入行有几个数字 type==-1?两个数字:三个数字
j=0,nj = s.size();
while(j<nj&&s[j]==' ') ++j;
bool isNegative = j<nj&&s[j]=='-'&&++j>0;//判断负数 如果是负数自加索引指针j
if(j<nj&&isdigit(s[j])){
c=0;
type=0;
while(j<nj&&isdigit(s[j])){
c=c*10+(s[j]-'0');
++j;
}
if(isNegative) c=-c;
}
if(b!=lastTaskId){//转折点
solve();
}
if(type==-1){//两个数 放入查询队列
if ((itTmpS = tmpSearch.find(b)) == tmpSearch.end()) {
vector<int> v(1,a);
tmpSearch.insert(pair<int, vector<int> >(b,v));
TS.insert(b);
}
else {
itTmpS->second.emplace_back(a);
}
}
else{//三个数 放入更新队列
if((itTmpU=tmpUpdate.find(b))==tmpUpdate.end()){
unordered_map<int,int> M;
M.insert(pair<int,int>(a,c));
tmpUpdate.insert(pair<int,unordered_map<int,int> >(b,M));
TU.insert(b);
}
else{
itTmpU->second.insert(pair<int,int>(a,c));
}
}
if(i==xk&&!tmpSearch.empty()){//转折点
solve();
}
lastTaskId=b;
}
return 0;
}
/*
5 10
1 2
1 3
1 4
1 5
2 3
2 4
2 5
3 4
3 5
4 5
1 27
1 1 1
2 1 2
3 1 3
4 1 4
5 1 5
1 1
2 1
3 1
4 1
5 1
1 2
2 2
3 2
4 2
5 2
1 10 10
2 11 9
1 11
2 11
3 11
4 11
5 11
1 12
2 12
3 12
4 12
5 12
15 13
1 2
2 3
3 4
4 5
1 6
6 7
7 8
8 9
1 10
10 11
11 12
12 13
14 15
6 28
1 1 1
1 2 2
1 6
2 7
13 7
9 7
5 7
3 14
8 14
5 14
11 14
9 25
5 25
13 25
9 29 3
5 29 4
13 29 5
1 53
2 59 6
2 59
1 1000
3 1000
8 1000
9 1000
10 1000
13 1000
14 1000
15 1000
*/
时间压力测试代码
注意在enque函数加入如下代码限制主链长度不超过500
输出时记得输出到文件,输出到控制台时耗时高很多。
测试时时耗大概:5000ms
#include<iostream>
#include<vector>
#include<map>
#include<set>
#include<unordered_map>
#include<unordered_set>
#include<string>
#define DEBUG 1
#ifdef DEBUG
#include<fstream>
#include<ctime>
std::ofstream LOG("log.txt");
#endif
using namespace std;
vector<int> G[501];
vector<int> Links[501];
set<int> Q;
set<int>::iterator itQ;
unordered_map<int, unordered_map<int,vector<int> > > F;
unordered_map<int, unordered_map<int,vector<int> > >::iterator itF;
int n,m,t,k,u,v,a,b,c;
set<int> TS,TU;
set<int>::iterator itTS,itTU;
unordered_map<int, vector<int> > tmpSearch;
unordered_map<int, vector<int> >::iterator itTmpS;
unordered_map<int, unordered_map<int, int> > tmpUpdate;
unordered_map<int, unordered_map<int, int> > ::iterator itTmpU;
void enque(const int& time,const int& point){
#ifdef DEBUG
if(Links[point].size()>500) return;
#endif
unordered_map<int, unordered_map<int,vector<int> > >::iterator it = F.find(time);
if(it == F.end()){
Q.insert(time);
unordered_map<int,vector<int> > M;
M.insert(pair<int,vector<int> >(point,vector<int>(Links[point])));
F.insert(pair<int,unordered_map<int,vector<int> > >(time,M));
}
else{
unordered_map<int, vector<int> >::iterator itM = it->second.find(point);
if (itM == it->second.end()) {
it->second.insert(pair<int, vector<int> >(point, vector<int>(Links[point])));
}
else {
const vector<int>& vM = itM->second;
int n1 = Links[point].size(), n2 = vM.size();
if (n1 > n2 || n1 == n2&&Links[point].back() < vM.back()) {
itM->second = vector<int>(Links[point]);
}
}
}
}
void receiveChain() {
int timeQ = Q.empty() ? ::b : 0, timeT, flagQ=0, b = TS.empty()? ::b : *TS.begin();
do {
while(!TU.empty()&& (timeT = *(itTU = TU.begin())) < timeQ){
const unordered_map<int,int>& M = tmpUpdate.find(timeT)->second;
for (unordered_map<int,int>::const_iterator itM = M.begin(); itM != M.end(); ++itM){
Links[itM->first].emplace_back(itM->second);
enque(timeT + t, itM->first);
}
TU.erase(itTU);
tmpUpdate.erase(timeT);
}
if (flagQ == 1) {
const unordered_map<int,vector<int> >& M = F.find(timeQ)->second;
for (unordered_map<int,vector<int> >::const_iterator itM = M.begin(); itM != M.end(); ++itM) {
const int& v = itM->first;
const vector<int>& link = itM->second;
for (int i = 0, ni = G[v].size(), n1, n2; i<ni; ++i) {
n1 = link.size(), n2 = Links[G[v][i]].size();
if (n1<n2 || n1 == n2&&link.back() >= Links[G[v][i]].back()) continue;
Links[G[v][i]] = link;
enque(t + timeQ, G[v][i]);
}
}
F.erase(timeQ);
Q.erase(itQ);
continue;
}
flagQ = 1;
} while (!Q.empty() && (timeQ = *(itQ = Q.begin())) <= b);
}
void outputChain() {
for (itTS = TS.begin(); itTS != TS.end();++itTS) {
itTmpS = tmpSearch.find(*itTS);
const vector<int>& V = itTmpS->second;
itTmpU = tmpUpdate.find(itTmpS->first);
for (int i = 0, ni = V.size(), link_length, link_value, link_flag; i<ni; ++i) {
link_length = Links[V[i]].size();
link_flag = 0;
if (itTmpU != tmpUpdate.end()) {
const unordered_map<int, int>& M = itTmpU->second;
unordered_map<int, int>::const_iterator itM = M.find(V[i]);
if (itM != M.end()) {
++link_length;
link_flag = 1;
link_value = itM->second;
}
}
#ifdef DEBUG
LOG << link_length;
#endif
for (int j = 0, nj = Links[V[i]].size(); j<nj; ++j) {
#ifdef DEBUG
LOG << ' ' << Links[V[i]][j];
#endif
}
if (link_flag == 1) {
#ifdef DEBUG
LOG << ' ' << link_value;
#endif
}
#ifdef DEBUG
LOG << endl;
#endif
}
}
tmpSearch.clear();
TS.clear();
}
void updateChain() {
for(itTmpU=tmpUpdate.begin();itTmpU!=tmpUpdate.end();++itTmpU){
const unordered_map<int,int>& M = itTmpU->second;
const int & timeU = itTmpU->first;
for (unordered_map<int, int>::const_iterator itM = M.begin(); itM != M.end(); ++itM) {
Links[itM->first].emplace_back(itM->second);
enque(timeU + t, itM->first);
}
}
tmpUpdate.clear();
TU.clear();
}
void solve(){
receiveChain();
outputChain();
updateChain();
}
int main(){
#ifdef DEBUG
ifstream cin("input.txt");
clock_t c1 = clock();
#endif
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cin>>n>>m;
for(int i=0;i<m;++i){
cin>>u>>v;
G[u].emplace_back(v);
G[v].emplace_back(u);
}
for (int i = n; i > 0; --i) {
Links[i].emplace_back(0);
}
cin>>t>>k;
string s;
for(int i=0,j,nj,lastTaskId=1,xk=k-1;i<k;++i){
cin>>a>>b,c=-1;
getline(cin,s);
j=0,nj = s.size();
while(j<nj&&s[j]==' ') ++j;
bool isNegative = j<nj&&s[j]=='-'&&++j>0;
if(j<nj&&isdigit(s[j])){
c=0;
while(j<nj&&isdigit(s[j])){
c=c*10+(s[j]-'0');
++j;
}
if(isNegative) c=-c;
}
if(b!=lastTaskId){
solve();
}
if(c==-1){
if ((itTmpS = tmpSearch.find(b)) == tmpSearch.end()) {
vector<int> v(1,a);
tmpSearch.insert(pair<int, vector<int> >(b,v));
TS.insert(b);
}
else {
itTmpS->second.emplace_back(a);
}
}
else{
if((itTmpU=tmpUpdate.find(b))==tmpUpdate.end()){
unordered_map<int,int> M;
M.insert(pair<int,int>(a,c));
tmpUpdate.insert(pair<int,unordered_map<int,int> >(b,M));
TU.insert(b);
}
else{
itTmpU->second.insert(pair<int,int>(a,c));
}
}
if(i==xk&&!tmpSearch.empty()){
solve();
}
lastTaskId=b;
}
#ifdef DEBUG
clock_t c2 = clock();
cout << endl << c2 - c1 << "ms" << endl;
#endif
return 0;
}
#include<iostream>
#include<cstdlib>
#include<fstream>
#include<set>
using namespace std;
int main(){
int n = 500,m = 10000,t=rand()%1000+1,k=30000;
ofstream fout("input.txt");
set<pair<int,int> > S;
fout<<n<<" "<<m<<endl;
while(S.size()<m){
int u = rand()%500 + 1,v = rand()%500 +1;
pair<int,int> p;
if(u<v){
p = pair<int,int>(u,v);
}
else{
p = pair<int,int>(v,u);
}
if(S.find(p)==S.end()){
fout<<p.first<<" "<<p.second<<endl;
S.insert(p);
}
}
fout<<t<<" "<<k<<endl;
for(int i=0,a,b = 1,c;i<k;++i){
a = rand()%500 + 1;
if((rand()%100)>60){
if((rand()%100)>80){
b = b +(rand()%t) + (t*rand())%3;
}
else{
b = b +rand()%t;
}
}
c = 1*rand()*rand()*rand();
if((rand()%100)>30){
fout<<a<<" "<<b<<endl;
}
else{
fout<<a<<" "<<b<<" "<<c<<endl;
}
}
return 0;
}