连接格点
问题描述:
有一个M行N列的点阵,相邻两点可以相连。一条纵向的连线花费一个单位,一条横向的连线花费两个单位。某些点之间已经有连线了,试问至少还需要花费多少个单位才能使所有的点全部连通。
测试样例1
输入
输入样例
2 2
1 1 2 1
输出
输出样例
3
首先是一位不愿透露姓名的ljy dalao的简洁快速程序 撒花✿✿ヽ(°▽°)ノ✿
#include<cstdio> #include<algorithm> using namespace std; int f[1000001]; int father(int i) { if (f[i]!=i) f[i]=father(f[i]); return f[i]; } int main() { int i,j,n,m,s,x1,y1,x2,y2,p,q; freopen("grid.in ","r",stdin); freopen("grid.out","w",stdout); scanf("%d%d",&m,&n); s=0; for (i=1;i<=n*m;i++) f[i]=i; while (scanf("%d%d%d%d",&x1,&y1,&x2,&y2)==4) { p=father((x1-1)*n+y1); q=father((x2-1)*n+y2); if (p!=q) f[q]=p; } for (i=1;i<=n;i++)//先纵后横因为纵向权值小 for (j=1;j<m;j++) { p=father((j-1)*n+i); q=father(j*n+i); if (p!=q) {f[q]=p; s++;} } for (i=1;i<=m;i++) for (j=1;j<n;j++) { p=father((i-1)*n+j); q=father((i-1)*n+j+1); if (p!=q) {f[q]=p; s+=2;} } printf("%d",s); fclose(stdin); fclose(stdout); return 0; }
接下来是我复杂运行慢的辣鸡程序 (╯‵□′)╯炸弹!•••*~●
#include<cstdio> #include<algorithm> using namespace std; struct www { int x,y,w; }a[2000005]; int n,m,f[1000005],s,xa,xb,ya,yb,w,p; bool cmp(www a,www b) { return a.w<b.w; } int find(int x) { if (f[x]!=x) f[x]=find(f[x]); return f[x]; } int main() { freopen("grid.in","r",stdin); freopen("grid.out","w",stdout); scanf("%d%d",&m,&n); for (int i=1;i<=n*m;i++) f[i]=i; for (int i=1;i<=m;i++) for (int j=1;j<=n;j++) { int now=(i-1)*n+j,right=(i-1)*n+j+1,down=i*n+j; if (j<n) {a[++p].x=now; a[p].y=right; a[p].w=2;} if (i<m) {a[++p].x=now; a[p].y=down; a[p].w=1;} } while (scanf("%d%d%d%d",&xa,&ya,&xb,&yb)==4) { int wa=(xa-1)*n+ya,wb=(xb-1)*n+yb; f[find(wa)]=find(wb); } sort(a+1,a+p+1,cmp); for (int i=1;i<=p;i++) { int fx=find(a[i].x),fy=find(a[i].y); if (fx!=fy) { f[fx]=fy; s+=a[i].w; } } printf("%d",s); fclose(stdin); fclose(stdout); return 0; }
最终结论:我太菜啦!