数据规模比较大,我想到的是比较直观的宽度搜索算法。样例通过了。但是提交只有20分,运行超时。求效率更高的算法。
#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
#include<conio.h>
using namespace std;
const int Q = 1000000007;
//const int INF = 1e6+5;//最大弧长,相当于定义无限大
struct Edge{
int from, to;//dist是权值
//Edge(int u, int v, int d):from(u),to(v),dist(d){}
Edge(int u, int v):from(u),to(v){}
};
struct HeapNode{
int d;//距离
int u;//弧的编号
bool operator < (const HeapNode& rhs) const {
return d > rhs.d;
}
};
struct Tree{
int n;//顶点的个数
vector<long long> value;//顶点的权值
vector<Edge> edges;
vector<vector<int> > G;//保存边号
vector<bool> done; //是否已永久标号
vector<int> p; //顶点i的上一条边p[i]
vector<vector<bool> > status;
vector<int> d;
void init(int n){
this->n = n;
value.resize(n);
edges.clear();
G.resize(n, vector<int>());
done.clear();
p.resize(n);
status.clear();
d.clear();
//p.clear();
}
void addEdge(int from, int to){
edges.push_back(Edge(from, to));
int m = edges.size();
G[from].push_back(m-1);
G[to].push_back(m-1); //无向图
}
void bfs(int root, int end){
done.clear();
done.resize(n, false);
p[root] = -1;
//p.resize(n, -1);
queue<int> Q;
for(int i=0;i<G[root].size(); i++){
Edge& e = edges[G[root][i]];
int u;
if(e.from==root) u=e.to;
else u=e.from;
p[u] = G[root][i];
Q.push(G[root][i]);
}
done[root] = true;
while(!Q.empty()) {
int x = Q.front(); Q.pop();
Edge& e = edges[x];
int u;
if(done[e.from]) u=e.to;
else u=e.from;
if(done[u]) continue;
for(int i=0;i<G[u].size(); i++){
Edge& e = edges[G[u][i]];
int to;
if(u==e.from) to=e.to;
else to=e.from;
if(done[to]==false) {
p[to] = G[u][i];
if(to==end) break;
Q.push(G[u][i]);
}
}
done[u] = true;
}
}
void add_d(int u, int v, int d){
bfs(u,v);
//int g = p[v];
/*int g;
Edge& e = edges[p[v]];
if(e.from==v) g=e.to;
else g=e.from;
while(g!=u){
value[g]+=d;
Edge& e = edges[p[g]];
if(e.from==g) g=e.to;
else g=e.from;
}*/
int g = v;
while(1){
//cout<<g<<" ";
value[g] += d;
if(p[g]==-1) break;
Edge& e = edges[p[g]];
if(e.from==g) g=e.to;
else g=e.from;
}
//cout<<endl;
//getch();
}
void bfs2(int root){
done.clear();
done.resize(n, false);
p[root] = -1;
d.clear();
d.resize(n,1);
//p.resize(n, -1);
queue<int> Q;
for(int i=0;i<G[root].size(); i++){
Edge& e = edges[G[root][i]];
int u;
if(e.from==root) u=e.to;
else u=e.from;
p[u] = G[root][i];
d[u] = 2;
Q.push(G[root][i]);
}
done[root] = true;
while(!Q.empty()) {
int x = Q.front(); Q.pop();
Edge& e = edges[x];
int u;
if(done[e.from]) u=e.to;
else u=e.from;
if(done[u]) continue;
for(int i=0;i<G[u].size(); i++){
Edge& e = edges[G[u][i]];
int to;
if(u==e.from) to=e.to;
else to=e.from;
if(done[to]==false) {
//cout<<"aafscs";
p[to] = G[u][i];
d[to] = d[u]+1;
Q.push(G[u][i]);
}
}
done[u] = true;
}
}
void sum(int L, int R){
status.clear();
status.resize(n, vector<bool>(n,false));
long long ss = 0;
for(int i=1;i<n;i++){
bfs2(i);
//cout<<"i:"<<i<<" ";
for(int j=1;j<n;j++){
//cout<<d[j]<<" ";
if(d[j]>=L && d[j]<=R && !status[i][j]){
//cout<<j<<" ";
status[i][j] = true;
status[j][i] = true;
int g = j;
while(1){
ss = (ss+value[g])%Q;
if(p[g]==-1) break;
Edge& e = edges[p[g]];
if(e.from==g) g=e.to;
else g=e.from;
}
}
}
//cout<<endl;
}
cout<<ss<<endl;
}
void display(){
printf("acs\n");
for(int i=1;i<n;i++){
cout<<"结点:"<<i<<" "<<value[i]<<endl;
for(int j=0;j<G[i].size();j++){
Edge& e = edges[G[i][j]];
int u;
if(e.from==i) u=e.to;
else u=e.from;
cout<<u<<" ";
}
cout<<endl;
}
}
};
int main(){
ios::sync_with_stdio(false);
int T;
cin>>T;
for(int p=0;p<T;p++){
int n,m,L,R;
cin>>n>>m>>L>>R;
Tree S;
S.init(n+1);
for(int i=1;i<=n;i++){
cin>>S.value[i];
}
int temp;
for(int i=1;i<n;i++){
cin>>temp;
S.addEdge(temp,i+1);
}
//S.display();
int u,v,d;
for(int i=0;i<m;i++){
cin>>u>>v>>d;
S.add_d(u,v,d);
//S.display();
S.sum(L, R);
}
}
return 0;
}