1003 电话连线
2018-06-17 22:49:51来源:未知 阅读 ()
一个国家有n个城市。若干个城市之间有电话线连接,现在要增加m条电话线(电话线当然是双向的了),使得任意两个城市之间都直接或间接经过其他城市有电话线连接,你的程序应该能够找出最小费用及其一种连接方案。
输入文件的第一行是n的值(n<=100).
第二行至第n+1行是一个n*n的矩阵,第i行第j列的数如果为0表示城市i与城市j有电话线连接,否则为这两个城市之间的连接费用(范围不超过10000)。
输出文件的第一行为你连接的电话线总数m,第二行至第m+1行为你连接的每条电话线,格式为i j,(i<j), i j是电话线连接的两个城市。输出请按照Prim算法发现每一条边的顺序输出,起始点为1.
第m+2行是连接这些电话线的总费用。
5
0 15 27 6 0
15 0 33 19 11
27 33 0 0 17
6 19 0 0 9
0 11 17 9 0
2
1 4
2 5
17
n<=100
分类标签 Tags 点此展开
裸prim但是我上来就智障的敲了个kruskal也是醉了
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 struct node 7 { 8 int u; 9 int v; 10 int w; 11 }edge[10001]; 12 struct ans 13 { 14 int x; 15 int y; 16 }a[10001]; 17 int num=1; 18 int f[1001]; 19 int cmp(const node &a,const node &b) 20 { 21 return a.w<b.w; 22 } 23 int find(int x) 24 { 25 if(x!=f[x]) 26 f[x]=find(f[x]); 27 return f[x]; 28 } 29 void unionn(int x,int y) 30 { 31 int fx=find(x); 32 int fy=find(y); 33 f[fx]=fy; 34 } 35 int comp(const ans &a,const ans &b) 36 { 37 if(a.y>b.y)return 1; 38 if(a.y==b.y&&a.x<b.x)return 1; 39 return 0; 40 } 41 int now=1; 42 int main() 43 { 44 int n; 45 scanf("%d",&n); 46 for(int i=1;i<=n;i++)f[i]=i; 47 for(int i=1;i<=n;i++) 48 { 49 for(int j=1;j<=n;j++) 50 { 51 int p; 52 scanf("%d",&p); 53 if(j>i) 54 { 55 edge[num].u=i; 56 edge[num].v=j; 57 edge[num].w=p; 58 num++; 59 } 60 } 61 } 62 sort(edge+1,edge+num,cmp); 63 int k=0; 64 int tot=0; 65 int feiyong=0; 66 for(int i=1;i<=num;i++) 67 { 68 if(find(edge[i].u)!=find(edge[i].v)) 69 { 70 unionn(edge[i].u,edge[i].v); 71 //printf("%d %d\n",edge[i].u,edge[i].v); 72 if(edge[i].w!=0) 73 { 74 tot++; 75 feiyong=feiyong+edge[i].w; 76 //ans1[now]=edge[i].u; 77 //ans2[now]=edge[i].v; 78 a[now].x=min(edge[i].u,edge[i].v); 79 a[now].y=max(edge[i].u,edge[i].v); 80 k++; 81 now++; 82 } 83 84 } 85 if(k==n-1)break; 86 } 87 /*for(int i=1;i<=now;i++) 88 { 89 for(int j=i;j<=now;j++) 90 { 91 if(ans1[j]>ans1[j+1]) 92 { 93 swap(ans1[j],ans1[j+1]); 94 swap(ans1[j],ans2[j+1]); 95 } 96 } 97 }*/ 98 sort(a+1,a+now,comp); 99 printf("%d\n",tot); 100 for(int i=1;i<=now-1;i++) 101 { 102 printf("%d %d\n",a[i].x,a[i].y); 103 } 104 printf("%d",feiyong); 105 return 0; 106 }
1 #include <iostream> 2 #include <algorithm> 3 using namespace std; 4 const int MAXN = 105; 5 const int INF = 2147483647; 6 int i, j, n; 7 long long ans = 0; 8 int edge[MAXN][MAXN], key[MAXN], p[MAXN], vis[MAXN] = {0}, //edge表示存的边 key表示权值,p表示父亲,vis表示是否已经存在已生成的树中 9 f[MAXN], l[MAXN], m = 0; //f表示头,右边表示尾 10 int main() { 11 cin >> n; 12 for(i = 1; i <= n; i++)for(j = 1; j <= n; j++) cin >> edge[i][j]; 13 for(i = 1; i <= n; i++) key[i] = INF; 14 key[1] = 0; // 15 p[1] = 1; 16 int Mini, Min; 17 for(i = 0; i < n; i++) { //之需要加最多n条边,故循环n次 18 Min = INF; 19 for(j = 1; j <= n; j++) if(!vis[j] && key[j] < Min) { 20 Mini = j; //找key值最小的点,即与树相邻的节点的最小权值边 21 Min = key[j]; 22 } 23 vis[Mini] = 1; //设置访问过,即生成树已连接Mini这个节点 24 ans += key[Mini]; 25 if(key[Mini]) { 26 f[m] = min(p[Mini], Mini); //字典序的边 27 l[m++] = max(p[Mini], Mini); //同上 28 } 29 for(j = 1; j <= n; j++) //伪松弛,更新树临边节点的key值并维护p域 30 if(!vis[j] && edge[Mini][j] < key[j]) { 31 key[j] = edge[Mini][j]; 32 p[j] = Mini; 33 } 34 } 35 cout << m << endl; 36 for(i = 0; i < m; i++) cout << f[i] << ' ' << l[i] << endl; 37 cout << ans; 38 return 0; 39 }
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇:BZOJ 4816 数字表格
下一篇:2455 繁忙的都市
- 算法笔记刷题6 ( PAT 1003我要通过 ) 2020-05-08
- bzoj1003: [ZJOI2006]物流运输(最短路+DP) 2019-08-16
- P1003铺地毯 2019-08-16
- #leetcode刷题之路17-电话号码的字母组合 2019-03-13
- 『ACM C++』 Codeforces | 1003C - Intense Heat 2019-03-04
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash