这题一看数据,m,n都是十万级别的..顿时迷茫了....
百度了一下,看到列表里面有kruscal算法,就想着试一下..没想到过了..真的不是数据太水吗..
计算机1秒能算十亿次(这个是从别人博客上学习来的);
200000^2 好像有点大,就没敢用prim算法来算..所以没写..毕竟prim要查找,差不多是n^2复杂度..
上网搜了一下,竟然有一个人,还是唯一一个人用了prim..贴上代码膜拜一下;
kruscal一般在稀疏图的时候使用,比较快,稀疏图是个叫法吧,没有太确定的界限..不过N*(N-1)/2肯定是稠密图,用prim肯定比kruscal快的..
下面这个是自己写的kruscal算法.
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <algorithm> 5 using namespace std; 6 #define maxn 200005 7 #define INF 0x3f3f3f3f 8 int father[maxn]; 9 int n ,m; 10 struct node{ 11 int u , v; 12 int w; 13 }edge[maxn]; 14 void init() 15 { 16 for(int i = 0 ;i <= n ;i++) 17 father[i] = i; 18 } 19 int find(int x) 20 { 21 if(father[x]==x) 22 return x; 23 return father[x]=find(father[x]); 24 } 25 void unite(int x,int y) 26 { 27 int fx = find(x) , fy = find(y); 28 if(fx == fy) 29 return ; 30 father[fy] = fx; 31 } 32 bool cmp(node a , node b) 33 { 34 return a.w < b.w; 35 } 36 int kruscal(int t) 37 { 38 int res = 0,count = 0; 39 int u,v; 40 for(int i = 0 ;i < t; i++) 41 { 42 u = edge[i].u; 43 v = edge[i].v; 44 if(find(u)!=find(v)) 45 { 46 unite(u,v); 47 count++; 48 res += edge[i].w; 49 50 } 51 52 } 53 return res; 54 } 55 int main() 56 { 57 //freopen("2988.txt","r",stdin); 58 int a,b,d,total; 59 while(~scanf("%d %d",&m,&n)&&(m||n)) 60 { 61 total = 0; 62 init(); 63 for(int i = 0 ; i< n ; i++) 64 { 65 scanf("%d %d %d",&a,&b,&d); 66 edge[i].u = a ; 67 edge[i].v = b; 68 edge[i].w = d; 69 total += d; 70 } 71 sort(edge,edge+n,cmp); 72 int sum = kruscal(n); 73 printf("%d ",total-sum); 74 } 75 return 0; 76 }
下面这个是网上大牛用prim写的..两种算法都是700ms级别的,后面这个算法稍微慢一点;
1 #include<iostream> 2 using namespace std; 3 4 struct Edge{ 5 int l,r,w; 6 int next; 7 }; 8 int head[200001]; 9 Edge edges[400001]; 10 int dis[200001]; 11 bool visit[200001]; 12 int n,m; 13 int loc; 14 15 void addEdge(int l,int r,int w){ 16 edges[loc].l=l,edges[loc].r=r,edges[loc].w=w,edges[loc].next=head[l],head[l]=loc++; 17 } 18 19 int prim(){ 20 int out=0; 21 memset(dis,-1,sizeof(dis)); 22 memset(visit,false,sizeof(visit)); 23 dis[0]=0; 24 int i; 25 for(i=1;i<=n;i++){ 26 int sm=INT_MAX; 27 int id; 28 int j; 29 for(j=0;j<n;j++){ 30 if(dis[j]<sm&&!visit[j]&&dis[j]!=-1){ 31 sm=dis[j]; 32 id=j; 33 } 34 } 35 out+=dis[id]; 36 visit[id]=true; 37 for(j=head[id];j!=-1;j=edges[j].next){ 38 if(dis[edges[j].r]==-1||edges[j].w<dis[edges[j].r]){ 39 dis[edges[j].r]=edges[j].w; 40 } 41 } 42 43 } 44 return out; 45 } 46 47 48 49 int main(){ 50 //freopen("a.txt","r",stdin); 51 while(scanf("%d%d",&n,&m)!=EOF){ 52 int all=0; 53 if(n==0&&m==0){ 54 break; 55 } 56 loc=0; 57 memset(head,-1,sizeof(head)); 58 59 int i; 60 for(i=1;i<=m;i++){ 61 int a,b,c; 62 scanf("%d%d%d",&a,&b,&c); 63 addEdge(a,b,c); 64 addEdge(b,a,c); 65 all+=c; 66 } 67 printf("%d ",all-prim()); 68 } 69 70 71 return 0; 72 }