CodeForces 125E MST Company(最小度限制生成树)
2017-09-04 22:02
585 查看
题意就不说了。
然后求最小度限制生成树的思路网上有很多。
下面是根据思路自己写的一个。
然后求最小度限制生成树的思路网上有很多。
下面是根据思路自己写的一个。
#include <cstdio> #include <vector> #include <queue> #include <algorithm> using namespace std; typedef long long LL; const int MAXN = 5000+5; const int inf = 1e9; int n,m,k; int ans;//最小k度限制生成树的总权值和 int p_min[MAXN],p[MAXN];//记录连接联通分量的最小权值、以及点 int mdu;//记录最小m度限制生成树的m struct edge { int u,v,w; int id; bool operator < (const edge &a)const { return w < a.w; } } edge[100005],dp[MAXN]; int tu[MAXN][MAXN];//记录权值 bool link[MAXN][MAXN];//记录是否连接 int pre[MAXN]; int findx(int x) { return pre[x] == x?x : pre[x] = findx(pre[x]); } void kruskal() { for(int i = 1; i <= n; ++i)pre[i] = i; for(int i = 0; i < m; ++i) { int u = edge[i].u; int v = edge[i].v; int w = edge[i].w; if(u == 1 || v == 1)continue; int fu = findx(u); int fv = findx(v); if(fu != fv) { pre[fv] = fu; link[u][v] = link[v][u] = 1; ans += w; } } } //求最小m度限制生成树 void solve1() { fill(p_min+1,p_min+1+n,inf); for(int i = 2; i <= n; ++i)if(tu[1][i] != -1) { int fa = findx(i); if(tu[1][i] < p_min[fa]) { p_min[fa] = tu[1][i]; p[fa] = i; } } for(int i = 1; i <= n; ++i)if(p_min[i] != inf) { mdu++; link[1][p[i]] = link[p[i]][1] = 1; ans += p_min[i]; } } //计算从1到某点路径中权值最大的边,且和1没有关系 void dfs(int u,int fa) { for(int v = 2; v <= n; ++v) { if(!link[u][v] || v == fa)continue;//没有边 if(dp[v].w != -inf)//可以更新 { if(tu[u][v] < dp[u].w)dp[v] = dp[u]; else dp[v].u = u,dp[v].v = v,dp[v].w = tu[u][v]; } dfs(v,u); } } //计算最小k度限制生成树 void solve2() { for(int i = mdu+1; i <= k; ++i) { for(int j = 1; j <= n; ++j)dp[j].w = -1; dp[1].w = -inf; for(int j = 1; j <= n; ++j)if(link[1][j])dp[j].w = -inf;//-inf表示搜不到它 dfs(1,0); int key = 0,minn = inf; for(int j = 2; j <= n; ++j) if(tu[1][j] != -1 && tu[1][j] - dp[j].w < minn) { minn = tu[1][j] - dp[j].w; key = j; } int u = dp[key].u; int v = dp[key].v; link[u][v] = link[v][u] = 0; link[1][key] = link[key][1] = 1; ans += minn; } } bool check_tree() { int cnt = 0; if(cnt == n-1)return 1; sort(edge,edge+m); for(int i = 1; i <= n; ++i)pre[i] = i; for(int i = 0; i < m; ++i) { int u = edge[i].u; int v = edge[i].v; u = findx(u); v = findx(v); if(u != v) { pre[v] = u; cnt++; if(cnt == n-1)return 1; } } return 0; } int ans_edge[MAXN]; int ans_cnt; int main() { scanf("%d%d%d",&n,&m,&k); for(int i = 1; i <= n; ++i) for(int j = i+1; j <= n; ++j)tu[i][j] = tu[j][i] = -1; int tot = 0; for(int i = 0; i < m; ++i) { scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w); edge[i].id = i+1; if(edge[i].u == 1 || edge[i].v == 1)tot++; tu[edge[i].u][edge[i].v] = tu[edge[i].v][edge[i].u] = edge[i].w; } if(tot < k || (n > 1&& k == 0))return 0*puts("-1"); if(!check_tree())return 0*puts("-1"); kruskal(); solve1(); //printf("%d %d\n",mdu,ans); solve2(); ans_cnt = 0; for(int i = 0; i < m; ++i) { int u = edge[i].u; int v = edge[i].v; if(link[u][v])ans_edge[ans_cnt++] = edge[i].id; } printf("%d\n",ans_cnt); for(int i = 0; i < ans_cnt; ++i)printf("%d ",ans_edge[i]); return 0; }
相关文章推荐
- Codeforces 125E MST Company (单度限制最小生成树)
- POJ 1639 度限制的最小生成树
- codeforces 76A Gift 最小生成树
- codeforces 888G Xor-MST Sollin算法求最小生成树,0-1异或True
- Codeforces 892/E Envy 最小生成树的query
- POJ 1639 Picnic Planning【度限制最小生成树】
- 最小度限制生成树
- pku 1639 Picnic Planning 最小度限制生成树
- CodeForces 472D Design Tutorial: Inverse the Problem (最小生成树+lca)
- 带有度限制的最小生成树
- Codeforces 827D Best Edge Weight (最小生成树 + 树链剖分/倍增/并查集)
- POJ - 1639 最小限制生成树
- 【POJ】1639 Picnic Planning 度限制最小生成树
- poj1639 Picnic Planning 最小度数限制生成树
- Codeforces 827 D 最小生成树+倍增 解题报告
- POJ 1639 最小度限制生成树
- POJ --- 1639 【k度限制最小生成树】
- Codeforces 125E MST Company(k度限制生成树)
- POJ 1639:Picnic Planning(最小度限制生成树)
- 最小度限制生成树