题意:给出n个点的坐标,要把n个点连通,使得总距离最小,可是有m对点已经连接,输入m,和m组a和b,表示a和b两点已经连接。
思路:两种做法。(1)用prim算法时,输入a,b。令mp[a][b]=0。然后进行一遍prim(2)Kruskal算法+并查集
代码:
//prim写法 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <string> #include <map> #include <stack> #include <vector> #include <set> #include <queue> #pragma comment (linker,"/STACK:102400000,102400000") #define pi acos(-1.0) #define eps 1e-6 #define lson rt<<1,l,mid #define rson rt<<1|1,mid+1,r #define FRE(i,a,b) for(i = a; i <= b; i++) #define FREE(i,a,b) for(i = a; i >= b; i--) #define FRL(i,a,b) for(i = a; i < b; i++) #define FRLL(i,a,b) for(i = a; i > b; i--) #define mem(t, v) memset ((t) , v, sizeof(t)) #define sf(n) scanf("%d", &n) #define sff(a,b) scanf("%d %d", &a, &b) #define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c) #define pf printf #define DBG pf("Hi\n") typedef long long ll; using namespace std; #define INF 0x3f3f3f3f #define mod 1000000009 const int maxn = 1005; const int MAXN = 2005; const int MAXM = 200010; const int N = 1005; struct Node { double x,y; }node[maxn]; int n,m; double mp[maxn][maxn]; double dist[maxn]; bool vis[maxn]; double Dis(Node n1,Node n2) { return sqrt((n1.x-n2.x)*(n1.x-n2.x)+(n1.y-n2.y)*(n1.y-n2.y)); } double prim() { int i,j,now; double mi; mem(vis,false); mem(dist,INF); for (i=1;i<=n;i++) dist[i]=mp[1][i]; dist[1]=0; vis[1]=true; for (i=1;i<=n;i++) { now=-1; mi=INF; for (j=1;j<=n;j++) { if (!vis[j]&&mi>dist[j]) { now=j; mi=dist[j]; } } if (now==-1) break; vis[now]=true; for (j=1;j<=n;j++) { if (!vis[j]&&dist[j]>mp[now][j]) dist[j]=mp[now][j]; } } double ans=0; for (i=1;i<=n;i++) ans+=dist[i]; return ans; } int main() { #ifndef ONLINE_JUDGE freopen("C:/Users/lyf/Desktop/IN.txt","r",stdin); #endif int i,j,u,v; while (~sf(n)) { for (i=1;i<=n;i++) scanf("%lf%lf",&node[i].x,&node[i].y); for (i=1;i<=n;i++) { for (j=1;j<=n;j++) if (i==j) mp[i][j]=0; else mp[i][j]=Dis(node[i],node[j]); } sf(m); for (i=0;i<m;i++) //在同一个联通块的距离直接赋为0 { sff(u,v); mp[u][v]=mp[v][u]=0; } printf("%.2f\n",prim()); } return 0; } //Kruskal+并查集写法 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <string> #include <map> #include <stack> #include <vector> #include <set> #include <queue> #pragma comment (linker,"/STACK:102400000,102400000") #define pi acos(-1.0) #define eps 1e-6 #define lson rt<<1,l,mid #define rson rt<<1|1,mid+1,r #define FRE(i,a,b) for(i = a; i <= b; i++) #define FREE(i,a,b) for(i = a; i >= b; i--) #define FRL(i,a,b) for(i = a; i < b; i++) #define FRLL(i,a,b) for(i = a; i > b; i--) #define mem(t, v) memset ((t) , v, sizeof(t)) #define sf(n) scanf("%d", &n) #define sff(a,b) scanf("%d %d", &a, &b) #define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c) #define pf printf #define DBG pf("Hi\n") typedef long long ll; using namespace std; #define INF 0x3f3f3f3f #define mod 1000000009 const int maxn = 1005; const int MAXN = 1000000; const int MAXM = 200010; const int N = 1005; struct Node { double x,y; }node[maxn]; struct Edge { int u,v; double len; }edge[MAXN]; int n,m,cnt; int father[maxn]; int cmp(Edge e1,Edge e2) { return e1.len<e2.len; } void init() { cnt=0; for (int i=0;i<=n;i++) father[i]=i; } double Dis(Node n1,Node n2) { return sqrt((n1.x-n2.x)*(n1.x-n2.x)+(n1.y-n2.y)*(n1.y-n2.y)); } int find_father(int x) { if (x!=father[x]) father[x]=find_father(father[x]); return father[x]; } double Kruskal() { int i,j; double ans=0; sort(edge,edge+cnt,cmp); for (i=0;i<cnt;i++) { int fu=find_father(edge[i].u); int fv=find_father(edge[i].v); if (fu!=fv) { ans+=edge[i].len; father[fu]=fv; } } return ans; } int main() { #ifndef ONLINE_JUDGE freopen("C:/Users/lyf/Desktop/IN.txt","r",stdin); #endif int i,j,u,v; while (~sf(n)) { init(); for (i=1;i<=n;i++) scanf("%lf%lf",&node[i].x,&node[i].y); for (i=1;i<n;i++) { for (j=i+1;j<=n;j++) { if (i==j) continue; else { double x=Dis(node[i],node[j]); edge[cnt].u=i; edge[cnt].v=j; edge[cnt++].len=x; } } } sf(m); for (i=1;i<=m;i++) { sff(u,v); int fu=find_father(u); int fv=find_father(v); if (fu!=fv) father[fu]=fv; } printf("%.2f\n",Kruskal()); } return 0; }
时间: 2024-10-13 07:04:56