图论500题http://blog.csdn.net/luomingjun12315/article/details/47438607
【最小生成树+并查集】
1、hdu 1856 基础并查集★
/* 转化为图论模型 求一个图的最大联通分量 用并查集,每个联通分量用一个集合维护,最后求集合元素个数的最大值 */ #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn = 10000010; int fa[maxn]; int ans[maxn]; void init(){ for(int i=0;i<maxn;++i){ fa[i] = i; } memset(ans , 0, sizeof(ans)); } int find(int u){ return u==fa[u] ? u : fa[u] = find(fa[u]); } void un(int u, int v){ int fu = find(u); int fv = find(v); fa[fv] = fu; } int main(){ int n; while(scanf("%d", &n)==1){ if(n==0){ printf("1\n"); continue; } init(); int u, v; int maxnum = -1; for(int i=0;i<n;++i){ scanf("%d%d", &u, &v); if(u>maxnum) maxnum = u; if(v>maxnum) maxnum = v; if(find(u)!=find(v)) un(u, v); } // ///test // for(int i=1;i<=maxnum;++i){ // cout << fa[i] << " "; // } // cout << endl; for(int i=1;i<=maxnum;++i){ ans[find(i)]++; } int maxans = -1; for(int i=1;i<=maxn;++i){ if(ans[i] > maxans) maxans = ans[i]; } printf("%d\n", maxans); } return 0; }
2、hdu 1102 基础最小生成树★ 错误原因还未找到
/* 克鲁斯卡尔算法 将边从小到大排序 */ #include<iostream> #include<cstdio> #include<algorithm> using namespace std; const int maxn = 10010; struct node{ int u; int v; int weight; } ; node edges[maxn]; bool cmp(const node & e1, const node & e2){ return e1.weight <= e2.weight; } int d[105]; //并查集 int find(int u){ return u==d[u] ? u : d[u] = find(d[u]); } void init(){ for(int i=0;i<105;++i){ d[i] = i; } } void un(int u, int v){ int fu = find(u); int fv = find(v); d[fv] = fu; } int main(){ int n; int en = 0; int w; init(); scanf("%d", &n); for(int i=1;i<=n;++i){ for(int j=1;j<=n;++j){ scanf("%d", &w); if(j>i){ edges[en].weight = w; edges[en].u = i; edges[en].v = j; en++; } } } int q; int u, v; scanf("%d", &q); for(int i=0;i<q;++i){ scanf("%d%d", &u, &v); if(find(u)!=find(v)) un(u, v); } int ans = 0; sort(edges, edges+en, cmp); for(int i=0;i<en;++i){ if(find(edges[i].u) != find(edges[i].v)){ ans+=edges[i].weight; un(edges[i].u, edges[i].v); } } printf("%d\n", ans); return 0; }