POJ1358 Agri-Net

题目链接

就是裸的最小生成树,复习一下。

prim算法:

G=(V,E),V是点集,E是边集

假设T=(U,TE)是最小生成树。U,TE初始化为空

首先从V中任取一点 假设取V1,然后U={V1},只要U是V的真子集,就从那些一个端点在T中,一个端点在T外的边中,找一条最短边。一直下去,直到找到n-1条边

找边使用 堆优化,复杂度(ElogV) 邻接表复杂度(V2

 1 #include<cstdio>
 2 #include<vector>
 3 #include<queue>
 4 #include<cstring>
 5 using namespace std;
 6 const int maxn=110;
 7 const int inf=0x3f3f3f3f;
 8 
 9 struct node{
10     int v,dis;
11     node(){}
12     node(int _v,int _dis){
13         v=_v;
14         dis=_dis;
15     }
16     bool operator<(const node &b) const {
17         return dis>b.dis;
18     }
19 };
20 
21 int n,dis[maxn];
22 vector<node> G[maxn];
23 bool vis[maxn];
24 
25 void prim() {
26     int ans=0,num=0;
27     priority_queue<node> pq;
28     for(int i=0;i<n;i++) {
29         vis[i]=false;
30         dis[i]=inf;
31     }
32     pq.push(node(0,0));
33     node f;
34     while(num<n&&!pq.empty()) {
35         do{
36            f=pq.top();
37            pq.pop();
38         }while(vis[f.v]&&!pq.empty());
39         if(!vis[f.v]) {
40             ans+=f.dis;
41             vis[f.v]=true;
42             num++;
43             for(int i=0;i<G[f.v].size();i++) {
44                 int v=G[f.v][i].v;
45                 if(!vis[v]) {
46                     if(dis[v]>G[f.v][i].dis) {
47                         dis[v]=G[f.v][i].dis;
48                         pq.push(node(v,dis[v]));
49                     }
50                 }
51             }
52         }
53     }
54     if(num<n) printf("-1
");//因为这里记录的是点的个数。不是边
55     else printf("%d
",ans);
56 }
57 
58 int main() {
59     while(~scanf("%d",&n)) {
60         memset(G,0,sizeof(G));
61         for(int i=0;i<n;i++) {
62             for(int j=0;j<n;j++) {
63                 int x;
64                 scanf("%d",&x);
65                 if(x) G[i].push_back(node(j,x));
66             }
67         }
68         prim();
69     }
70 }

krusual算法:

将图G中的边按权值从小到大选取,使选取的不与生成树构成回路。直到n-1条边为止

判断回路就用并查集搞一下。

 1 #include<cstdio>
 2 #include<vector>
 3 #include<queue>
 4 #include<cstring>
 5 #include<algorithm>
 6 using namespace std;
 7 const int maxn=110;
 8 const int inf=0x3f3f3f3f;
 9 
10 int n;
11 struct Edge{
12     int u,v,dis;
13     Edge(){}
14     Edge(int _u,int _v,int _dis) {
15         u=_u;
16         v=_v;
17         dis=_dis;
18     }
19     bool operator <(const Edge &b) const {
20         return dis<b.dis;
21     }
22 };
23 
24 vector<Edge> edge;
25 
26 int fa[maxn];
27 
28 int Find(int x) {
29     if(fa[x]==-1) return x;
30     else return fa[x]=Find(fa[x]);
31 }
32 
33 void Union(int x,int y) {
34     int fx=Find(x);
35     int fy=Find(y);
36     if(fx!=fy) {
37         fa[fx]=fy;
38     }
39 }
40 
41 int main() {
42     while(~scanf("%d",&n)) {
43         memset(fa,-1,sizeof(fa));
44         edge.clear();
45         for(int i=0;i<n;i++) {
46             for(int j=0;j<n;j++) {
47                 int x;
48                 scanf("%d",&x);
49                 if(x&&j<i) edge.push_back(Edge(i,j,x));
50             }
51         }
52         sort(edge.begin(),edge.end());
53         int num=0,ans=0;
54         for(int i=0;i<edge.size();i++) {
55             int u=edge[i].u,v=edge[i].v,dis=edge[i].dis;
56             if(Find(u)!=Find(v)) {
57                 num++;
58                 ans+=dis;
59                 Union(u,v);
60             }
61         }
62         if(num==n-1) printf("%d
",ans);
63         else printf("-1
");
64     }
65 }
原文地址:https://www.cnblogs.com/ACMerszl/p/10667146.html