ccf csp 201903-5 317号任务

这道题数据规模太大,总是超时。求大佬给100分代码,实在不知道怎么改进。

我的解题思路是对每个点进行一次Dijkstra算法,找出符合要求的最近的点。

#include
#include 
#include
#include
const int INF = 1005;//最大弧长,相当于定义无限大 
const int MAXN = 10005;//顶点的最大数量 
using namespace std;
struct Edge{
 int from, to, dist;//dist是权值 
 Edge(int u, int v, int d):from(u),to(v),dist(d){}
};
struct HeapNode{
 int d;//距离
 int u;//弧的编号
 bool operator < (const HeapNode& rhs) const {
  return d > rhs.d;
 } 
};
struct Dijkstra{
 int n;//顶点的个数 
 int m;//边的个数
 int k;//需要找的行星发动机据点的个数 
 vector edges;
 vector G[MAXN];
 int is_star[MAXN]; //标志是否为行星发动机据点
  
 vector fine_star;//保存已经找到的行星发送机据点 
 bool done[MAXN];    //是否已永久标号 
 int d[MAXN];        //原点s到各个点的最短距离 
 int p[MAXN];        //最短路径中的上一条弧
 
 void init(int n, int k){
  memset(is_star, 0, sizeof(is_star));
  this->n = n;
  this->k = k;
  for(int i=0;i Q;
  Q.push((HeapNode){0,s});
  while(!Q.empty()) {
   HeapNode x = Q.top(); Q.pop();
   int u = x.u;
   if(done[u]) continue;
   done[u] = true;
   for(int i=0;i d[u] + e.dist) {
     d[e.to] = d[u] + e.dist;
     p[e.to] = G[u][i];
     Q.push((HeapNode){d[e.to], e.to});
    }
   }
   if(is_star[u]){
    fine_star.push_back(u);
    if(fine_star.size()==k) return;
   }
  }
 }
 int solve(int s){
  dijkstra(s);
  int sum=0;
  for(int i=0;i > v(n, vector(n, INF));
 for(int i=0;i>a>>b>>w;
  a--;
  b--;
  if(a==b) continue;
  if(v[a][b]>w){
   v[a][b]=w;
   v[b][a]=w;
   D.addEdge(a,b,w);
   D.addEdge(b,a,w);
  }
 }
}
int main(){
 ios::sync_with_stdio(false);
 int n,m,k;
 cin>>n>>m>>k;
 Dijkstra D;
 D.init(n,k);
 for(int i=0;i>D.is_star[i];
 read_edges(D, m);
 for(int i=0;i

结果超时了,后来想到,所有的边其实都是无向边,两个点之间的最短距离其实只用算一遍。所以可以保存,减少计算量。

#include
#include 
#include
#include
const int INF = 1005;//最大弧长,相当于定义无限大 
const int MAXN = 10005;//顶点的最大数量 
using namespace std;
struct Edge{
 int from, to, dist;//dist是权值 
 Edge(int u, int v, int d):from(u),to(v),dist(d){}
};
struct HeapNode{
 int d;//距离
 int u;//弧的编号
 bool operator < (const HeapNode& rhs) const {
  return d > rhs.d;
 } 
};
struct Dijkstra{
 int n;//顶点的个数 
 int m;//边的个数
 int k;//需要找的行星发动机据点的个数 
 vector edges;
 vector G[MAXN];
 int is_star[MAXN]; //标志是否为行星发动机据点
  
 vector fine_star;//保存已经找到的行星发送机据点 
 bool done[MAXN];    //是否已永久标号 
 vector > d;     //原点s到各个点的最短距离 
 //int p[MAXN][MAXN];        //最短路径中的上一条弧
 
 void init(int n, int k){
  memset(is_star, 0, sizeof(is_star));
  this->n = n;
  this->k = k;
  for(int i=0;i Q;
  Q.push((HeapNode){0,s});
  while(!Q.empty()) {
   HeapNode x = Q.top(); Q.pop();
   int u = x.u;
   if(done[u]) continue;
   done[u] = true;
   for(int i=0;i d[s][u] + e.dist) {
     d[s][e.to] = d[s][u] + e.dist;
     d[e.to][s] = d[s][e.to];
     //p[e.to] = G[u][i];
     Q.push((HeapNode){d[s][e.to], e.to});
    }
    else if(d[s][e.to] < INF && e.to > v(n, vector(n, INF));
 for(int i=0;i>a>>b>>w;
  a--;
  b--;
  if(a==b) continue;
  if(v[a][b]>w){
   v[a][b]=w;
   v[b][a]=w;
   D.addEdge(a,b,w);
   D.addEdge(b,a,w);
  }
 }
}

int main(){
 ios::sync_with_stdio(false);
 int n,m,k;
 cin>>n>>m>>k;
 Dijkstra D;
 D.init(n,k);
 for(int i=0;i>D.is_star[i];
 read_edges(D, m);
 D.solve();
 return 0;
}

结果还是超时,只有30分。
应该还有更好的算法,精力有限,求助各位大佬。

你可能感兴趣的:(CSP)