图论——最小生成树
学习图论也有好长时间了一些基本的模板再打一遍,今天的是最小生成树的Kruskal算法,自己一遍打出来尽管很fake但也是自己一遍打出来的有一点点感悟,Kruskal是运用贪心的思想来实现的先找最小边 一次一次加入。
#include<iostream> #include<cmath> #include<cstring> #include<string> #include<ctime> #include<cstdio> #include<algorithm> #include<map> #include<vector> #include<stack> #include<queue> #include<iomanip> using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } struct bwy { int x,y,z; }b[200002]; int ans=0; int len=1; int f[5009]; int n,m; int getfather(int x) { if(x==f[x]) return x; return f[x]=getfather(f[x]); } int my(bwy x,bwy y) { return x.z<y.z; } void Kruskal() { for(int i=1;i<n;i++) { for(int j=1;j<=m;j++) { int xx=getfather(b[j].x); int yy=getfather(b[j].y); if(xx!=yy) { f[xx]=yy; len++; ans+=b[j].z; } if(len==n) return; } } } int main() { //freopen("1.in","r",stdin); n=read();m=read(); for(int i=1;i<=n;i++) f[i]=i; for(int i=1;i<=m;i++) { int x,y,z; x=read();y=read();z=read(); b[i].x=x;b[i].y=y;b[i].z=z; } sort(b+1,b+1+m,my); Kruskal(); if(len==n)printf("%d\n",ans); else printf("orz\n"); return 0; }
在这里本人不是一遍a掉的,tle了原因是少加了 if(len==n) return;这句话导致把全部的边全部便利了一遍这点要注意!因为sort已经排过序了所以一旦选够所有的边即可直接返回,剩下的边一定没有后来的更优。
背灯和月就花阴,已是十年踪迹十年心。