比较好的讲解:http://blog.csdn.net/wsniyufang/article/details/6747392

view code//首先为除根之外的每个点选定一条入边,这条入边一定要是所有入边中最小的。
//现在所有的最小 入边都选择出来了,如果这个入边集不存在有向环的话,我们
//可以证明这个集合就是该图的最小树形图。这个证明并不是很难。如果存在有向
//环的话,我们就要将这 个有向环所称一个人工顶点,同时改变图中边的权。假
//设某点u在该环上,并设这个环中指向u的边权是in[u],那么对于每条从u出发的
//边(u, i, w),在新图中连接(new, i, w)的边,其中new为新加的人工顶点; 对
//于每条进入u的边(i, u, w),在新图中建立边(i, new, w-in[u])的边。为什么
//入边的权要减去in[u],这个后面会解释,在这里先给出算法的步骤。然后可以
//证明,新图中最小树形图的权加上旧图中被收缩 的那个环的权和,就是原图中
//最小树形图的权。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
typedef long long ll;
const int INF = 1<<30;
const int N = 600;
const int M = N*N;
int n, m, lev[55], pre[N], begid[N];
int s, t, in[N<<1], p[N], vis[N], id[N]; struct edge
{
int u, v, w;
edge() {}
edge(int u, int v, int w):u(u),v(v),w(w) {}
}e[M];
int ecnt; inline void addedge(int u, int v, int w)
{
e[ecnt++] = edge(u, v, w);
} int DirMst(int rt, int num)//根结点,结点数目
{
int ans = 0;
while(1)
{
for(int i=0; i<num; i++) in[i] = INF;
for(int i=0; i<ecnt; i++)
{
int u = e[i].u, v = e[i].v;
if(in[v]>e[i].w && u!=v)
{
in[v] = e[i].w;
pre[v] = u;
}
}
for(int i=0; i<num; i++) if(i!=rt && in[i]==INF) return -1; int cnt = 0;
memset(id, -1, sizeof(id));
memset(vis, -1, sizeof(vis));
in[rt] = 0;
for(int i=0; i<num; i++)
{
ans += in[i];
int v = i;
while(vis[v]!=i && v!=rt && id[v]==-1)// 找环
{
vis[v] = i;
v = pre[v];
}
while(v!=rt && id[v]==-1)// 有环,重新编号
{
int u = pre[v];
for(;u!=v; u=pre[u]) id[u]=cnt;
id[v] = cnt++;
}
}
if(cnt==0) break;
for(int i=0; i<num; i++) if(id[i]==-1) id[i]=cnt++;// 不在环内,重新编号
for(int i=0; i<ecnt; i++)// 更新环外点和环缩点后的点的距离
{
int u = e[i].u, v = e[i].v;
e[i].u = id[u];
e[i].v = id[v];
if(id[u]!=id[v]) e[i].w -= in[v];
}
num = cnt;
rt = id[rt];
}
return ans;
} void solve()
{
ecnt = 0;
for(int i=1; i<=n; i++) scanf("%d", lev+i);
for(int i=1; i<=n; i++) begid[i] = begid[i-1]+lev[i-1]+1;
s = 0, t = begid[n]+lev[n]+1;
for(int i=1; i<=n; i++)
{
addedge(s, begid[i], 0);
for(int j=0; j<lev[i]; j++)
{
addedge(begid[i]+j+1, begid[i]+j, 0);
}
}
int c, l, d, r, w;
for(int i=0; i<m; i++)
{
scanf("%d%d%d%d%d", &c, &l, &d, &r, &w);
int u = begid[c]+l ,v = begid[d]+r;
addedge(u, v, w);
}
printf("%d\n", DirMst(s, t));
} int main()
{
// freopen("in.txt", "r", stdin);
while(scanf("%d%d", &n, &m)>0 && (n|m)) solve();
return 0;
}

hdu 4966 GGS-DDU (最小树形图)的更多相关文章

  1. HDU 4966 GGS-DDU(最小树形图)

    n个技能,每个技能有0-a[i]的等级,m个课程,每个课程需要前置技能c[i]至少达到lv1[i]等级,效果是技能d[i]达到lv2[i]等级,花费w[i]. 输出最小花费使得全技能满级(初始全技能0 ...

  2. HDU 4009 Transfer water 最小树形图

    分析:建一个远点,往每个点连建井的价值(单向边),其它输水线按照题意建单向边 然后以源点为根的权值最小的有向树就是答案,套最小树形图模板 #include <iostream> #incl ...

  3. hdu 2121 , hdu 4009 无定根最小树形图

    hdu 2121 题目:给出m条有向路,根不确定,求一棵最小的有向生成树. 分析:增加一个虚拟节点,连向n个节点,费用为inf(至少比sigma(cost_edge)大).以该虚拟节点为根求一遍最小树 ...

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

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

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

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

  6. HDU 6141 I am your Father!(最小树形图+权值编码)

    http://acm.hdu.edu.cn/showproblem.php?pid=6141 题意: 求最大树形图. 思路: 把边的权值变为负值,那么这就是个最小树形图了,直接套模板就可以解决. 有个 ...

  7. HDU 6141 I am your Father!(最小树形图)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=6141 [题目大意] 给出一个有向图,求1点为根的最小树形图使得第n个点的直接父亲编号最小 [题解] ...

  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 (无定根最小树形图)

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

随机推荐

  1. IO流(一)__File对象和字符流FileWriter FileReader

    IO流:IO流用来处理设备之间的数据传输,Java对于流的操作对象都在IO包中将外设中的数据读取到内存中:输入将内存的数写入到外设中:输出 流分为字节流和字符流字符流的由来:其实就是字节流读取文字字节 ...

  2. 代码验证浏览器是否支持html audio 和video

    <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8&quo ...

  3. 由Vue引发的getter和setter思考

    公司的新项目决定使用Vue.js来做,当我打印出Vue实例下的data对象里的属性时,发现了一个有趣的事情: 它的每个属性都有两个相对应的get和set方法,我觉的这是多此一举的,于是去网上查了查Vu ...

  4. 总结CSS3新特性(Transition篇)

    CSS 过渡(transition), 是 CSS3 规范的一部分, 用来控制 CSS 属性的变化速率. 可以让属性的变化过程持续一段时间,而不是立即生效.比如,将元素的颜色从白色改为黑色,通常这个改 ...

  5. 对比MS Test与NUnit Test框架

    前言: 项目中进行Unit Test时,肯定会用到框架,因为这样能够更快捷.方便的进行测试. .Net环境下的测试框架非常多,在这里只是对MS Test和NUnit Test进行一下比较, 因为这两个 ...

  6. Snort - manual 笔记(一)

    Chapter 1 Snort Overview This manual is based on Writing Snort Rules by Martin Roesch and further wo ...

  7. Linux学习心得之 jnlp的文件和java应用程序安全设置

    作者:枫雪庭 出处:http://www.cnblogs.com/FengXueTing-px/ 欢迎转载 jnlp的文件和java应用程序安全设置 1.前言2. jnlp的文件打开3.java应用程 ...

  8. 小谈KVC中KeyPath的集合运算符

    由于知识点比较简单,这里不再陈述一大堆的原理,直入主题. KVC中的集合运算符有以下三类: 1.简单集合运算符:@avg.@sum.@max.@min.@count (只能用在集合对象中,对象属性必须 ...

  9. Android 常用数据适配器ArrayAdapter

    接着上篇文章<Android 采用Layout Inflater创建一个View对象>,本文采用常用数据适配器ArrayAdapter 新建项目后,在layout文件夹下新建list_it ...

  10. sleep() 和 wait() 的区别

    好多面经上都出现了,有必要好好熟悉一下 区别: 1.wait() 可以指定时间,也可以不指定(等五分钟你进来,或者是不叫你一直等着):sleep()必须指定时间(不能一睡不起) 2.wait()是Ob ...