传送门
思路:
题目要求每次连边都要输出最小生成树的边权和。如果在线直接套用最小生成树模板肯定会超时,考虑离线处理。记录每一插入边的时间,在所有边都插入完成后排序一遍就可以求最小生成树(按照插入时间的前后对边进行取舍)。
标程:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<string> #include<vector> #include<stack> #include<deque> #include<queue> #include<map> #include<set> using namespace std; #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) #define maxn 6001 typedef long long LL; LL n,w,cnt,ans; LL fa[maxn]; struct hh { LL l,r,w,tim; }t[maxn]; inline LL read() { LL xs=0,kr=1;char ls; ls=getchar(); while(!isdigit(ls)) { if(!(ls^45)) kr=-1; ls=getchar(); } while(isdigit(ls)) { xs=(xs<<1)+(xs<<3)+(ls^48); ls=getchar(); } return xs*kr; } inline bool cmp(const hh&l,const hh&r) { return l.w<r.w; } inline LL find(LL u) { if(u!=fa[u]) fa[u]=find(fa[u]); return fa[u]; } inline void kruskal(LL num) { for(LL i=1;i<=w;i++) fa[i]=i; for(LL i=1;i<=w;i++) { if(t[i].tim>num) continue; LL r1=find(t[i].l),r2=find(t[i].r); if(r1!=r2) { fa[r1]=r2; ans+=t[i].w; cnt++; } if(cnt==n-1) {printf("%lld ",ans);return;} } printf("-1 "); } int main() { n=read();w=read(); for(LL i=1;i<=w;i++) { t[i].l=read();t[i].r=read();t[i].w=read();t[i].tim=i; } sort(t+1,t+w+1,cmp); for(LL i=1;i<=w;i++) { ans=0,cnt=0; kruskal(i); } return 0; }