ural Electrification Plan 最小生成树,多个源点
多个源点,虚拟成一个超点
题意:有很多岛,有些岛上有电站,岛与岛之间铺光缆可以互相通电。求使全部岛通电的最小代价。
本来是很朴素的最小生成树,但是不止一个岛有电站就使得这个问题变成多个源点的问题
处理是重新构造图,将所有电站当作一个点,边(电站,无电岛)
最小生成树可以有超点,那最短路可不可以呢?联想上一道行星的题,求从底层一个点到顶层点的最短路,那可不可以把最顶的节点当成一个超点??怎么实现?这道题目测不可以。再仔细想,比如单源最短路dijstra算法球的是源点到每个点的最短距离,所以终止是一个还是多个并不影响。
生成树要的是未加入tree的点与树中连接边最小的,所以可以有。
再想,网络流的可不可以。。这个不熟悉。。留着。。
const int N=110; const int INF=21460000; struct edge{ int x,y,c; bool operator < (const edge& a)const { return c<a.c; } }e[N*N]; int n,k; int Index[N],fa[N],mat[N][N]; int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);} int main() { int x,y,ans,cnt; cin >> n >> k; memset(Index,0,sizeof(Index));
for(int i=0;i<k;i++){ cin >> x; Index[x]=1; }
k=2; for(int i=1;i<=n;i++){ if(Index[i])continue; Index[i]=k++; } memset(mat,INF,sizeof(mat)); for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ int tcost; cin >> tcost; mat[Index[i]][Index[j]]=min(mat[Index[i]][Index[j]],tcost); } } cnt=0; for(int i=1;i<k;i++){ for(int j=i+1;j<k;j++){ e[cnt].x=i;e[cnt].y=j;e[cnt++].c=mat[i][j]; } } sort(e,e+cnt); // for(int i=0;i<cnt;++i) printf("%d %d %d \n",e[i].u,e[i].v,e[i].val ); // printf("\n"); ans=0; for(int i=1;i<k;i++)fa[i]=i; for(int i=0;i<cnt;i++){ int l,r; l=find(e[i].x);r=find(e[i].y); if(l!=r){ fa[r]=l; ans+=e[i].c; } } cout << ans << endl; return 0; }