poj1679,次小生成树的学习
昨天总结MST的模板,也写的差不多了吧
总之两种方法,kruskal和prim
麻烦的可能就是生成MST的唯一性的判定
原理很简单,先找MST,然后枚举MST上每条边,方法是删除该边再找MST,如果能找到MST并且权值等于第一次找到的,就不唯一了
http://poj.org/problem?id=1679
# include <iostream> # include <cstdio> # include <algorithm> # include <cstring> using namespace std; //先求出最小生成树,然后删除这棵树上的每条边求MST,求的时候要判断是否是MST struct edge{ int u, v, w, f; friend bool operator < (const edge &a, const edge &b){ return a.w < b.w; } }e[100 * 100 + 10]; int pre[110]; int n, m; int find(int x){ int s; for(s = x; pre[s] >= 0; s = pre[s]); while(s != x){ int t = pre[x]; pre[x] = s; x = t; } return s; } void Union(int x, int y){ int u = find(x); int v = find(y); if(u == v) return;//如果在同一棵树上 if(pre[u] > pre[v]){ pre[u] += pre[v]; pre[v] = u; }else{ pre[v] += pre[u]; pre[u] = v; } } int kruskal(int f){ int w = 0; int num = 0; memset(pre, -1, sizeof pre); for(int i = 0; i < m; i ++){ if(e[i].f == 2) continue; int u = e[i].u; int v = e[i].v; if(find(u) != find(v)){ w += e[i].w; if(f)e[i].f = 1; num ++; Union(u, v); } if(num >= n - 1) break; } if(num == n-1) return w; else return -1;//说明没有找到MST } int main(){ int tcase; scanf("%d", &tcase); while(tcase --){ scanf("%d%d", &n, &m); for(int i = 0; i < m; i ++){ scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w); e[i].f = 0; } sort(e, e + m); int w = kruskal(1); int flag = 0; for(int i = 0; i < m; i ++){ if(e[i].f == 0)continue; e[i].f ++; int tmp = kruskal(0); e[i].f --; //printf("%d ---\n", tmp); if(tmp != -1 && tmp == w){ flag = 1; break; } } if(flag) puts("Not Unique!"); else printf("%d\n", w); } return 0; } /* //牛人做法,拿来当模板用 int const INF=1000000000; int const maxn=105; int mark[maxn],map[maxn][maxn],mst[maxn]; int n,m; void prim(){ int i,j,k,ans=0,min,v,flag=0; for (i=1;i<=n;i++){ mark[i]=0; mst[i]=map[1][i]; } mark[1]=1; for (i=1;i<n;i++){ min=INF; for (j=1;j<=n;j++){ if (!mark[j] && mst[j]<min){ min=mst[j]; v=j; } } k=0; //------------------------------ //如果要选的点到已选的点,还有一条边权值相同,就 NO 了 for (j=1;j<=n;j++){ if (mark[j] && min==map[v][j])k++; } if (k>1){flag=1;break;} //------------------------------ ans+=min; mark[v]=1; for (j=1;j<=n;j++){ if (!mark[j] && map[v][j]<mst[j])mst[j]=map[v][j]; } } if (flag)cout<<"Not Unique!"<<endl; else cout<<ans<<endl; } int main() { int cas,i,j,p,q,w; cin>>cas; while (cas--) { cin>>n>>m; for (i=1;i<=n;i++) for (j=1;j<=n;j++) map[i][j]=INF; while (m--) { cin>>p>>q>>w; map[q][p]=map[p][q]=w; } prim(); } return 0; } */
posted on 2012-08-02 10:08 louzhang_swk 阅读(178) 评论(0) 编辑 收藏 举报