hdu 2121 无固定根的最小树形图
2016-08-07 20:11
225 查看
题目链接
解析
本题为不是固定根的最小树形图,我们可以虚拟出一根来,然后在把这个根跟每个点相连,相连的点可以设为无穷大,或者设为所有边和大一点,比如为r,然后就可以利用最小树形图进行计算了,计算出的结果减去r,如果比r还大就可以认为通过这个虚拟节点我们连过原图中两个点,即原图是不连通的,我们就可以认为不存在最小树形图。关于输出最小根也挺简单,在找最小入弧时,如果这条弧的起点是虚拟根,那么这条弧的终点就是要求的根。 但是我们根据最小入边的性质,可知,如果没缩点,必然找不到那个根,因为虚拟根连的边都非常大。但是缩点后,找到的必然是最小的那个序号的根。代码
#include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <algorithm> #include <vector> #include <cmath> using namespace std; const int INF=0x3f3f3f3f; const int maxn = 1000+100; typedef long long LL; int deg[maxn]; struct node { int u, v; LL w; node () {} node (int _u, int _v, int _w) { u = _u; v = _v; w = _w; } }edge[maxn*maxn], p[100000+10]; LL in[maxn]; int vis[maxn], id[maxn], pre[maxn]; int pos; LL Directed_MST(int root, int n, int m, node e[]) { LL ret = 0; while (1) { //第一步:找到入边最小边 for (int i=0; i<n; i++) in[i] = INF; for (int i=0; i<m; i++) { int u = e[i].u, v = e[i].v; if (e[i].w < in[v] && u != v) { in[v] = e[i].w; pre[v] = u; if (u == root) //找到与源点相连的点就是树形图的根 pos = i; } } for (int i=0; i<n; i++) { //没有入边,就不会产生最小树形图 if (i == root) continue; if (in[i] == INF) return -1; } int cntnode = 0; memset(id, -1, sizeof(id)); memset(vis, -1, sizeof(vis)); // 第二步:找环 in[root] = 0; for (int i=0; i<n; i++) { ret += in[i]; int v = i; while (vis[v] != i && id[v] == -1 && v != root) { vis[v] = i; v = pre[v]; } if (v != root && id[v] == -1) { for (int u=pre[v]; u!=v; u=pre[u]) id[u] = cntnode; id[v] = cntnode++; } } if (cntnode == 0) break; for (int i=0; i<n; i++) { if (id[i] == -1) id[i] = cntnode++; } //第三步:缩点、重新标记 for (int i=0; i<m; i++) { int v = e[i].v; e[i].u = id[e[i].u]; e[i].v = id[e[i].v]; if (e[i].u != e[i].v) e[i].w -= in[v]; } n = cntnode; root = id[root]; } return ret; } int main() { int n, m; while (~scanf("%d%d", &n, &m)) { memset(deg, 0, sizeof(deg)); memset(pre, 0, sizeof(pre)); memset(id, -1, sizeof(id)); memset(vis, -1, sizeof(vis)); LL sum = 0; for (int i=0; i<m; i++) { int u, v; LL w; scanf("%d%d%lld", &u, &v, &w); edge[i] = node(u, v, w); sum += w; } sum++; for (int i=m; i<n+m; i++) { edge[i] = node(n, i-m, sum); } LL ans = Directed_MST(n, n+1, n+m, edge); if (ans == -1 || ans-sum >= sum) puts("impossible"); else printf("%lld %d\n", ans-sum, pos-m); printf("\n"); } return 0; }
相关文章推荐
- hdu 2121 Ice_cream’s world II(无固定根最小树形图)
- HDU 2121 Ice_cream’s world II(无固定根最小树形图、找最小根)
- HDU 2121 Ice_cream's world II 朱刘算法求无固定根最小树形图
- hdu 2121(没有固定根的最小树形图)
- HDU 2121 无固定根的最小树形图
- HDU 2121 Ice_cream’s world II 无固定根的最小树形图以及最小根
- hdu 2121 最小树形图 朱刘算法
- HDU 4009 Transfer water 朱刘算法求无固定根最小树形图
- HDU 2121 Ice_cream’s world II(最小树形图)
- hdu 2121(无根最小树形图)
- hdu 2121 , hdu 4009 无定根最小树形图
- hdu 4009 Transfer water(无固定根最小树形图)
- HDU 2121 Ice_cream’s world II 最小树形图
- [HDU 2121] Ice_cream’s world II 最小树形图
- HDU 2121 Ice_cream’s world II(无定根最小树形图)
- hdu 2121+4009 最小树形图
- hdu 4009 Transfer water 有固定根的最小树形图
- HDU 2121 Ice_cream’s world II 最小树形图 模板
- HDU 2121 Ice_Cream's World II (最小树形图)
- hdu 2121 Ice_cream’s world II(无根结点最小树形图)