Floyd 超时 30分
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define inf 0x3f3f3f3f
static const int N=10001;
int E[N][N],kind[N];
struct Node{
int k,e;
}tmp[N];
bool cmp(Node P,Node Q){
if(P.k==Q.k) return P.e<Q.e;
return P.k>Q.k;
}
int main(){
int n,m,k;
cin>>n>>m>>k;
for(int i=1;i<=n;i++){
cin>>kind[i];
}
//初始化
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j) E[i][j]=0;
else E[i][j]=inf;
}
}
//去重边
int x,y,w;
for(int i=1;i<=m;i++){
cin>>x>>y>>w;
E[y][x]=E[x][y]=min(E[x][y],w);
}
//Floyd
for(int t=1;t<=n;t++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
E[i][j]=min(E[i][j],E[i][t]+E[t][j]);
}
}
}
//筛选行星点并排序
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
tmp[j].e=E[i][j];
tmp[j].k=kind[j];
}
sort(tmp+1,tmp+n+1,cmp);
int cnt = 0;
int sum = 0;
for(int j=1;j<=n;j++){
if(tmp[j].k==1&&tmp[j].e!=inf){
sum+=tmp[j].e;
cnt++;
}else continue;
if(cnt==k) break;
}
cout<<sum<<endl;
}
//输出
return 0;
}
SPFA 超时30分
但空间内存明显降了两个数量级,超时原因可能为NxM(M<<N),应当SAPA() MxN(M<<N)
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define inf 0x3f3f3f3f //宏定义后没有分号
static const int N=1e4+1;
static const int M=1e5+10;
struct edge{
int to;
long long val;
edge(){ }
edge(int a,long long b){
to = a;
val = b;
}
};
struct node_tmp{
int k;
long long e;
}T[N];
bool cmp(node_tmp P,node_tmp Q){
if(P.k==Q.k) return P.e<Q.e;
return P.k>Q.k;
}
long long dis[N];
bool vis[N];
int kind[N];
vector<edge> mp[M];
void SPFA(int s,int n){
//初始化内存
memset(vis,false,sizeof(vis));
// memset(dis,inf,sizeof(dis));
for(int i=1;i<=n;i++) dis[i]=inf;
//清空队列
queue<int> q;
if(!q.empty()) q.pop();
//初始化初始节点
dis[s]=0;
vis[s]=true;
q.push(s);
//出队列
while(!q.empty()){
int top=q.front();
q.pop();
vis[top]=false;
for(int i=0;i<mp[top].size();i++){
int v = mp[top][i].to;
//top--->v;
if(dis[v]>dis[top]+mp[top][i].val){
dis[v]=dis[top]+mp[top][i].val;
if(!vis[v]){
vis[v]=true;
q.push(v);
}
}
}
}
}
int main(){
int n,m,k;
cin>>n>>m>>k;
vector<int> center;
for(int i=1;i<=n;i++){
cin>>kind[i];
if(kind[i]==1) center.push_back(i);
}
// for(int i=0;i<=n;i++) mp[i].clear(); //多次用到需清空
int x,y;
long long w;
for(int i=1;i<=m;i++){
cin>>x>>y>>w;
mp[x].push_back(edge(y,w));
mp[y].push_back(edge(x,w));
}
for(int i=1;i<=n;i++){
long long sum=0;
SPFA(i,n);
for(int j=1;j<=n;j++){
T[j].k=kind[j];
T[j].e=dis[j];
}
sort(T+1,T+n+1,cmp);
for(int j=1;j<=n&&j<=k;j++){
if(T[j].e!=inf){
sum+=T[j].e;
}
}
cout<<sum<<endl;
}
return 0;
}
SPFA 100分
计算多源路径的时候,只需要计算行星节点的路径,然后进行转置排序汇总就可以大大减少计算量!下面附上满分代码!
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define inf 0x3f3f3f3f //宏定义后没有分号
static const int N=1e5+1;
static const int M=1e5+10;
struct edge{
int to;
long long val;
edge(){ }
edge(int a,long long b){
to = a;
val = b;
}
};
long long dis[N];
bool vis[N];
int kind[N];
vector<edge> mp[M];
void SPFA(int s,int n){
//初始化内存
memset(vis,false,sizeof(vis));
// memset(dis,inf,sizeof(dis));
for(int i=1;i<=n;i++) dis[i]=inf;
//清空队列
queue<int> q;
if(!q.empty()) q.pop();
//初始化初始节点
dis[s]=0;
vis[s]=true;
q.push(s);
//出队列
while(!q.empty()){
int top=q.front();
q.pop();
vis[top]=false;
for(int i=0;i<mp[top].size();i++){
int v = mp[top][i].to;
//top--->v;
if(dis[v]>dis[top]+mp[top][i].val){
dis[v]=dis[top]+mp[top][i].val;
if(!vis[v]){
vis[v]=true;
q.push(v);
}
}
}
}
}
int main(){
int n,m,k;
cin>>n>>m>>k;
vector<int> center;
for(int i=1;i<=n;i++){
cin>>kind[i];
if(kind[i]==1) center.push_back(i);
}
// for(int i=0;i<=n;i++) mp[i].clear(); //多次用到需清空
int x,y;
long long w;
for(int i=1;i<=m;i++){
cin>>x>>y>>w;
mp[x].push_back(edge(y,w));
mp[y].push_back(edge(x,w));
}
vector<long long> dis_[n+1];
for(int i=0;i<center.size();i++){
int start = center[i];
SPFA(start,n);
//cout<<start<<":";
for(int j=1;j<=n;j++){
//cout<<dis[j]<<" ";
if(dis[j]!=inf){
dis_[j].push_back(dis[j]);
}
}
//cout<<endl;
}
for(int i=1;i<=n;i++){
long long sum = 0;
sort(dis_[i].begin(),dis_[i].end());
for(int j=0;j<dis_[i].size()&&j<k;j++){
sum+=dis_[i][j];
}
cout<<sum<<endl;
}
return 0;
}