原题链接:https://www.luogu.org/problem/show?pid=1194
本题首先要注意三个地方:
第一行先输入a,再输入b,因为看反活活TLE了3次
边权为0的时候是没有优惠的,不能加边,如果边权超过a(这是个假的优惠),加边的时候加入a。
假如整张图都是0,那么就没有边读入了,然后我们就必须手动写入n-1条边。(在这里WA了两次)
结束这些后,我们就可以做裸的最小生成树了,假设买了任意的一件东西,然后就可以统计边权,最后加上一个a,作为第一件物品的价格。
#include<cstdio> #include<algorithm> using namespace std; void read(int &y) { y=0;char x=getchar(); while(x<'0'||x>'9') x=getchar(); while(x>='0'&&x<='9') { y=y*10+x-'0'; x=getchar(); } } int n,m,a,b,tot,ans,f[505]; struct edge { int u,v,w; }e[300005]; bool cmp(edge x,edge y) { return x.w<y.w; } void add(int u,int v,int w) { e[++m].u=u; e[m].v=v; e[m].w=w; } int find(int x) { if(x==f[x]) return x; return f[x]=find(f[x]); } int main() { read(a);read(n); for(int i=1;i<=n;i++) f[i]=i; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { read(b); if(i<j&&b!=0) add(i,j,min(a,b)); } } for(int i=2;i<=n;i++) add(1,i,a); sort(e+1,e+m+1,cmp); for(int i=1;i<=m;i++) { if(find(e[i].u)!=find(e[i].v)) { f[find(e[i].u)]=find(e[i].v); ans+=e[i].w; tot++; if(tot==n-1) break; } } printf("%d",ans+a); return 0; }