【解题思路】这题先看了NotOnlySuccess的解题思路,即设置虚根再处理的做法;弄了一个上午,再次有种赶脚的感觉~~如果需要找出为什么需要去比所有权值之和更大的数为新增的虚边的话,一开始我理解仅是找比最大边权值要大的数就够了,因为这样就已经满足了不会提前找到虚边的情况,但如果是这样的话那就很难判断这样一种情况:生成的最小树形图(含虚根)有两条边是从虚根出来的。

 #include<cstdio>
#include<cstring>
#define SIZE 1002
#define MAXN 20004 using namespace std; const int INF = <<;
int nv, ne, aimroot;
int vis[SIZE], pre[SIZE], num[SIZE];
int inLength[SIZE]; struct Edge{
int u, v, w;
}edge[MAXN]; void addedge(int u, int v, int w)
{//添加虚根与原图中其他点相连的边
edge[ne].u = u;
edge[ne].v = v;
edge[ne].w = w;
return;
} bool Traverse(int& res, int root)
{
nv++;
while(true)
{
for(int i=; i<nv; ++i) inLength[i] = INF;
for(int i=; i<ne; ++i)
{
int& u = edge[i].u;
int& v = edge[i].v;
if(edge[i].w < inLength[v] && u != v)
{
//不管结点的Id号怎样变化,固定的边所在的位置是不会变的,根据边在edge数组中存储的位置与起初边的Id号的对应关系
//就能理解下面为什么要这样输出
if(u == root) aimroot = i;
inLength[v] = edge[i].w;
pre[v] = u;
}
}
for(int i=; i<nv; ++i)
if(i != root && inLength[i] == INF) return false;
int newnum = ;
inLength[root] = ;
memset(vis, -, sizeof(vis));
memset(num, -, sizeof(num));
for(int i=; i<nv; ++i)
{
res += inLength[i];
int v = i;
while(vis[v] != i && num[v] == - && v != root)
{
vis[v] = i;
v = pre[v];
}
if(vis[v] == i)
{
for(int u=pre[v]; u != v; u = pre[u])
num[u] = newnum;
num[v] = newnum++;
}
}
if(newnum == ) return true;
for(int i=; i<nv; ++i)
if(num[i] == -) num[i] = newnum++;
for(int i=; i<ne; ++i)
{
int u = edge[i].u;
int v = edge[i].v;
edge[i].u = num[u];
edge[i].v = num[v];
if(edge[i].u != edge[i].v)
edge[i].w -= inLength[v];
}
nv = newnum;
root = num[root];
} } int main()
{
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
#endif
while(scanf("%d%d", &nv, &ne) != EOF)
{
int u, v, w, sum = ;
for(int i=; i<ne; ++i)
{
scanf("%d%d%d", &u, &v, &w);
edge[i].u = u;
edge[i].v = v;
edge[i].w = u == v ? INF+ : w;
sum += w;
}
sum++;
int temp = ne;
for(int i=; i<nv; ++i, ++ne)
addedge(nv, i, sum);
int res = ;
//res < 2*sum 设立这个条件是因为考虑到这种情况,虚根引出两条出边,这是不允许的,必须承认这是虚根,你得在原图中找到一个根
//这个条件成立了,说明有两条以上的虚边引出
if(Traverse(res, nv) && res < *sum)
//结合上面addedge函数中的说明,得到的aimroot存储的是你初始新存储虚边是在edge的下标,此下标大于或等于原图边的数目(边是从
//从零下标开始存储
printf("%d %d\n\n", res-sum, aimroot-temp);
else
printf("impossible\n\n");
}
return ;
}

HDU ACM 2121 Ice_cream’s world II (无根最小树形图)的更多相关文章

  1. HDU - 2121 Ice_cream’s world II 无根最小树形图

    HDU - 2121 :http://acm.hdu.edu.cn/showproblem.php?pid=2121 比较好的朱刘算法blog:https://blog.csdn.net/txl199 ...

  2. hdu 2121 Ice_cream’s world II (无定根最小树形图)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2121 题目大意: 有n个点,有m条单向路,问这n个点组成最小树形图的最小花费. 解题思路: 1:构造 ...

  3. hdu 2121无根最小树形图要建一个虚拟节点

    #include<stdio.h> #include<string.h> #define inf 999999999 #define N 1100 struct node { ...

  4. HDU 2121 Ice_cream’s world II 不定根最小树形图

    题目链接: 题目 Ice_cream's world II Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Ja ...

  5. hdoj 2121 Ice_cream’s world II 【没有最低树的根节点】

    称号:pid=2121" target="_blank">hdoj 2121 Ice_cream's world II 题意:题目是一道躶题,给n个点,m条边的有向 ...

  6. hdu 2121 Ice_cream’s world II

    Ice_cream’s world II http://acm.hdu.edu.cn/showproblem.php?pid=2121 Time Limit: 3000/1000 MS (Java/O ...

  7. HDU 2121 Ice_cream’s world II 最小树形图 模板

    开始学习最小树形图,模板题. Ice_cream’s world II Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32 ...

  8. HDU 2121——Ice_cream’s world II——————【最小树形图、不定根】

    Ice_cream’s world II Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64 ...

  9. HDU 2121 Ice_cream’s world II 最小树形图

    这个题就是需要求整个有向带权图的最小树形图,没有指定根,那就需要加一个虚根 这个虚根到每个点的权值是总权值+1,然后就可以求了,如果求出来的权值大于等于二倍的总权值,就无解 有解的情况,还需要输出最根 ...

随机推荐

  1. 3.cadence创建元器件

    1.打开OrCAD Capture 然后可以新建工程,也可以直接建library (打开  后 选择:OrCAD Capture CIS) 背景颜色 Options > Preferences ...

  2. [lintcode the-smallest-difference]最小差(python)

    题目链接:http://www.lintcode.com/zh-cn/problem/the-smallest-difference/ 给定两个整数数组(第一个是数组 A,第二个是数组 B),在数组 ...

  3. Selenium系列教程(2)

    Selenium RC(Selenium远程控制) Selenium RC是一个用Java编写的,允许用户使用无论哪种编程语言对基于Web的应用程序构建测试脚本的工具.Selenium RC克服了Se ...

  4. URAL1495. One-two, One-two 2(dp)

    1495 牵扯一点数位 保存数的时候我是按2进制保存的 把1当作0算 把2当作1算 滚动数组 dp[i][j][(g*10+j)%n] = min(dp[i][j][(g*10+j)%n],dp[i- ...

  5. hdu1054(二分图匹配)

    题意很简单,在一颗树上找最小点覆盖. 将树染成黑白两色,构成一张二分图,然后最大匹配==最小点覆盖即可,所以一次匈牙利就可以求出来了 hdu1054 #include <iostream> ...

  6. HTML5_拖放

    拖放(Drag 和 drop)是 HTML5 标准的组成部分.拖放是一种常见的特性,即抓取对象以后拖到另一个位置.在 HTML5 中,拖放是标准的一部分,任何元素都能够拖放. 支持的浏览器:Inter ...

  7. git plumbing 更加底层命令解析-深入理解GIT

    原文: http://rypress.com/tutorials/git/plumbing 本文详细介绍GIT Plumbing--更加底层的git命令,你将会对git在内部是如何管理和呈现一个项目r ...

  8. 用AngularJS开发下一代Web应用 系列入门基础教程

    开篇介绍 AngularJS是什么东西?我觉得不用再描述了.可自行去充电一下.按照惯例,让我们先看看一个Hello World的开门简介吧. <!doctype html> <htm ...

  9. UVa (一道比较复杂的广搜) 816 Abbott’s Revenge

    题意: 给出一个迷宫,在迷宫的节点处,面向某个方向只能向给定的方向转弯.给出起点和终点输出迷宫的最短路径,这里指的是刚刚离开起点的时刻,所以即使起点和终点重合路径也非空. 分析: 用三个变量来表示状态 ...

  10. You must SET PASSWORD before executing this statement解决

    [转载] MySql5.6操作时报错:You must SET PASSWORD before executing this statement解决 转载: http://blog.csdn.net/ ...