首先读题与自我欺骗,觉得多个井不知道怎么处理,看到联通整个牧场以为是只有一个井......
然后关于点的不知道怎么处理,于是把点与边一起排序:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 using namespace std; 5 #define debug(x) cout<<#x<<" = "<<x<<endl; 6 const int maxn=307; 7 int n,minn=0x7f7f7f7f,nod; 8 int w[maxn],map[maxn][maxn],head[maxn],num,fa[maxn]; 9 struct Edge{ 10 bool node; 11 int next,from,to,dis; 12 bool vis; 13 }edge[maxn*maxn]; 14 void add(int from,int to,int dis){ 15 edge[++num].next=head[from]; 16 edge[num].from=from; 17 edge[num].to=to; 18 edge[num].dis=dis; 19 head[from]=num; 20 } 21 bool cmp(Edge a,Edge b){ 22 return a.dis<b.dis; 23 } 24 int find(int x){ 25 if(fa[x]==x) return x; 26 return fa[x]=find(fa[x]); 27 } 28 void merge(int x,int y){ 29 int fx=find(x);int fy=find(y); 30 if(fx!=fy) fa[fx]=fy; 31 } 32 int kruskal(){ 33 for(int i=1;i<=n;i++) fa[i]=i; 34 int ans=0;int cnt=0; 35 for(int i=1;i<=num;i++){ 36 if(edge[i].node==true){ 37 if(edge[i].vis==false){ 38 edge[i].vis=true; 39 ans+=edge[i].dis;cnt++; 40 } 41 } 42 else{ 43 int u=edge[i].from;int v=edge[i].to; 44 if(edge[u].vis==true&&edge[v].vis==true) continue; 45 if(edge[u].vis==true&&edge[v].vis==false){ 46 edge[v].vis=true; 47 ans+=edge[i].dis; 48 merge(u,v);cnt++; 49 } 50 if(edge[u].vis==false&&edge[v].vis==true){ 51 edge[u].vis=true; 52 ans+=edge[i].dis; 53 merge(u,v);cnt++; 54 } 55 if(edge[u].vis==false&&edge[v].vis==false){ 56 edge[u].vis=true;edge[v].vis=true; 57 ans+=edge[i].dis; 58 merge(u,v);cnt+=2; 59 } 60 } 61 if(cnt==n) return ans; 62 } 63 } 64 int main(){ 65 cin>>n; 66 for(int i=1;i<=n;i++){ 67 cin>>w[i]; 68 edge[++num].node=true; 69 edge[num].dis=w[i]; 70 if(w[i]<minn){ 71 minn=w[i]; 72 nod=num; 73 } 74 } 75 for(int i=1;i<=n;i++) 76 for(int j=1;j<=n;j++) 77 cin>>map[i][j]; 78 for(int i=1;i<=n;i++) 79 for(int j=i+1;j<=n;j++) 80 if(map[i][j]!=0){ 81 add(i,j,map[i][j]); 82 add(j,i,map[i][j]); 83 } 84 sort(edge+1,edge+num+1,cmp); 85 cout<<kruskal()+minn<<endl; 86 return 0; 87 }
是错的,不懂
然后看了题解,就是建一个超级源点,既保证了从一个点开始计算每棵树,又保证了最小
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 using namespace std; 5 const int maxn=307; 6 int n,minn=0x7f7f7f7f; 7 int val[maxn],map[maxn][maxn],head[maxn],num,fa[maxn]; 8 struct Edge{ 9 int next,from,to,dis; 10 }edge[maxn*maxn]; 11 void add(int from,int to,int dis){ 12 edge[++num].next=head[from]; 13 edge[num].from=from; 14 edge[num].to=to; 15 edge[num].dis=dis; 16 head[from]=num; 17 } 18 bool cmp(Edge a,Edge b){ 19 return a.dis<b.dis; 20 } 21 int find(int x){ 22 if(fa[x]==x) return x; 23 return fa[x]=find(fa[x]); 24 } 25 void merge(int x,int y){ 26 int fx=find(x);int fy=find(y); 27 if(fx!=fy) fa[fx]=fy; 28 } 29 int kruskal(){ 30 for(int i=1;i<=n;i++) fa[i]=i; 31 int ans=0,cnt=0; 32 for(int i=1;i<num;i++){ 33 int x=edge[i].from;int y=edge[i].to; 34 int fx=find(x);int fy=find(y); 35 if(fx!=fy) {merge(fx,fy);cnt++;ans+=edge[i].dis;} 36 if(cnt==n) return ans; 37 } 38 } 39 int main(){ 40 cin>>n; 41 for(int i=1;i<=n;i++) {cin>>val[i];add(0,i,val[i]);} 42 for(int i=1;i<=n;i++) 43 for(int j=1;j<=n;j++) 44 cin>>map[i][j]; 45 for(int i=1;i<=n;i++) 46 for(int j=1;j<=n;j++) 47 add(i,j,map[i][j]); 48 sort(edge+1,edge+num+1,cmp); 49 cout<<kruskal()<<endl; 50 return 0; 51 }
这种想法以前接触过不止一次
在跑SPFA的时候,邓神就说过建一个超级源点,不必枚举每个点
后来有点权,有边权的这种类似问题也做过
难受......