比赛 csp2025模拟练习3 评测结果 AAAAAAAAAA
题目名称 Minimum Cost Roads 最终得分 100
用户昵称 梦那边的美好TE 运行时间 1.821 s
代码语言 C++ 内存使用 71.16 MiB
提交时间 2025-10-30 11:13:49
显示代码纯文本
#include <bits/stdc++.h>
#define int long long
#define pii pair<int,int>
#define mp make_pair
using namespace std;
const int N=2005;
int n,m,w[N][N],c[N][N],f[N],val[N][N],co[N][N];
int ver[N<<1],to[N<<2],nxt[N<<2],idx=1;
int dis[N<<1],mk[N<<1],edge[N],tot,ans,cnt,id;
priority_queue<pii>q;
void add(int x,int y){
	to[++idx]=y,nxt[idx]=ver[x],ver[x]=idx;
}
struct node{int u,v,w;}e[N];
bool cmp(node a,node b){
	return a.w<b.w;
}
int dijsktra(int s,int t){
	memset(dis,0x3f,sizeof(dis));
	memset(mk,0,sizeof(mk));
	q.push(mp(0,s)),mk[s]=1,dis[s]=0;
	while(q.size()){
		int x=q.top().second;
		q.pop();
		for(int i=ver[x];i;i=nxt[i]){
			int y=to[i];
			if((x==s&&y==t)||(x==t&&y==s))continue;
			if(dis[y]>dis[x]+val[x][y]){
				dis[y]=dis[x]+val[x][y];
				q.push(mp(-dis[y],y));
			} 
		}
	}
	return dis[t];
}
int found(int x){
	return f[x]==x?x:f[x]=found(f[x]);
}
signed main(){
	freopen("Roads.in","r",stdin);
	freopen("Roads.out","w",stdout);
	scanf("%lld %lld",&n,&m);
	memset(w,0x3f,sizeof(w));
	for(int i=1,u,v,len,cost;i<=m;i++){
		scanf("%lld %lld %lld %lld",&u,&v,&len,&cost);
		if(len<w[u][v]){
			w[u][v]=w[v][u]=len;
			c[u][v]=c[v][u]=cost;
		}else if(len==w[u][v]){
			c[u][v]=c[v][u]=min(c[u][v],cost);
		}
	}
	for(int i=1;i<=n;i++)f[i]=i;
	for(int i=1;i<=n;i++){
		for(int j=i+1;j<=n;j++){
			if(w[i][j]==0){
				e[++cnt]=node{i,j,c[i][j]};
			}
		}
	}
	sort(e+1,e+1+cnt,cmp);
	for(int i=1,u,v;i<=cnt;i++){
		u=found(e[i].u);
		v=found(e[i].v);
		if(u!=v)f[u]=v,ans+=e[i].w;
	} 
	memset(val,0x3f,sizeof(val));
	for(int i=1;i<=n;i++){
		for(int j=i+1;j<=n;j++){
			if(w[i][j]==0x3f3f3f3f3f3f3f3f)continue;
			if(w[i][j]==0)continue;
			int u=found(i),v=found(j);
			int len=w[i][j],cost=c[i][j];
			if(len<val[u][v]){
				val[u][v]=val[v][u]=len;
				co[u][v]=co[v][u]=cost;
			}else if(len==val[u][v]){
				co[u][v]=co[v][u]=min(co[u][v],cost);
			}
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=i+1;j<=n;j++){
			if(val[i][j]!=0x3f3f3f3f3f3f3f3f){
				add(i,j),add(j,i);
				edge[++tot]=idx;
			}
		}
	}
	for(int i=1;i<=tot;i++){
		int e=edge[i],u=to[e],v=to[e^1];
		if(dijsktra(u,v)>val[u][v]){
			ans+=co[u][v];
		}
	}
	printf("%lld\n",ans);
	return 0;
}