题意:在一个无向图中,给你几个源点,找出把所有点连接到源点后最小的消费;
可以利用并查集:
先用结构体把每个边存起来,再按照消费大小排序。之后从消费小的到大的一个个尝试,两个点需要连接的话,连接上同时把消费也算上去;
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <string> const int inf = 0x3f3f3f; using namespace std; int n,k; int fa[10000+7]; struct node { int from,to; int c; }a[10007]; bool cmp(node a,node b) { return a.c<b.c; } void init(){ for(int i=1;i<=n;i++) fa[i] = i; } int find(int x) { if(fa[x]==x)return x; else return fa[x] = find(fa[x]); } int uni(int x,int y) { if(fa[x]==-1&&fa[y]==-1)return 0; //(**) int px = find(x); int py = find(y); if(px==py)return 0; else { fa[px] = py; return 1; } } int main(){ scanf("%d%d",&n,&k); init(); for(int i=1;i<=k;i++) { int x; scanf("%d",&x); fa[x]=-1; //这个操作我其实不是很明确,我以我的理解加上了(**)这句, } //表示源点之间不用连接,但是别人写的好像不用加这句话。 int cnt =0; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { int cost; scanf("%d",&cost); if(cost==0)continue; a[++cnt].c=cost; a[cnt].from = i; a[cnt].to =j; } } sort(a+1,a+1+cnt,cmp); int ans = 0; for(int i=1;i<=cnt;i++) { if(uni(a[i].from,a[i].to)) { ans += a[i].c; } } printf("%d\n",ans); return 0; }
我自己就做了一个预处理,(直接把读入的用uni连接起来
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <string> const int inf = 0x3f3f3f; using namespace std; int n,k; int fa[10000+7]; struct node { int from,to; int c; }a[10007]; bool cmp(node a,node b) { return a.c<b.c; } void init(){ for(int i=1;i<=n;i++) fa[i] = i; } int find(int x) { if(fa[x]==x)return x; else return fa[x] = find(fa[x]); } int uni(int x,int y) { int px = find(x); int py = find(y); if(px==py)return 0; else { fa[px] = py; return 1; } } int main(){ scanf("%d%d",&n,&k); init(); int last=-1; for(int i=1;i<=k;i++) { int x; scanf("%d",&x); if(last!=-1) { int suibian; suibian =uni(last,x); //不理解别人把fa[x]=-1的操作; last = x; //自己就先预处理连接好了; } else last=x; } int cnt =0; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { int cost; scanf("%d",&cost); if(cost==0)continue; a[++cnt].c=cost; a[cnt].from = i; a[cnt].to =j; } } sort(a+1,a+1+cnt,cmp); int ans = 0; for(int i=1;i<=cnt;i++) { if(uni(a[i].from,a[i].to)) { ans += a[i].c; } } printf("%d\n",ans); return 0; }