BZOJ 4349: 最小树形图(最小树形图->朱刘算法)
2017-10-17 18:56
441 查看
4349: 最小树形图
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 379 Solved: 167
[Submit][Status][Discuss]
Description
小C现在正要攻打科学馆腹地------计算机第三机房。而信息组的同学们已经建好了一座座堡垒,准备迎战。小C作为一种高度智慧的可怕生物,早已对同学们的信息了如指掌。攻打每一个人的堡垒需要一个代价,而且必须攻打若干次才能把镇守之人灭得灰飞烟灭。
当小C在绞尽脑汁想攻打方案时,突然从XXX的堡垒中滚出来一个纸条:一个惊人的秘密被小C发现了:原来各个堡垒之间会相互提供援助,但是当一个堡垒被攻打时,他对所援助的堡垒的援助就会停止,因为他自己已经自身难保了。也就是说,小C只要攻打某个堡垒一次之后,某些堡垒就只需要花更小的代价攻击了。
现在,要你求消灭全机房要用掉代价最小多少。
Input
第一行一个数N,(N<=50),表示机房修建的堡垒数。接下来N行,每行两个数,第一个实数Ai表示攻打i号堡垒需要的代价Ai(0<Ai<=1000)。第二个数Bi(0<Bi<100)表示i号堡垒需要被攻打Bi次。
接下来一个数k,表示总共有k组依赖关系。
接下来k行每行三个数x,y,z(x,y,为整数,z为实数),表示攻打过一次x号堡垒之后,攻打y号堡垒就只要花z的代价,保证z比y原来的代价小。
不需要攻打的城堡不允许攻打。
Output
一行,一个实数表示消灭全机房要用的最小代价,保留两位小数。Sample Input
310.00 1
1.80 1
2.50 2
2
1 3 2.00
3 2 1.50
Sample Output
15.50HINT
Source最小树形图模板题,下面介绍求最小树形图的步骤:(概念不再赘述,不懂自行百度)
1、找到除了root以为其他点的权值最小的入边。用In[i]记录
2、如果出现除了root以为存在其他孤立的点,则不存在最小树形图。
3、找到图中所有的环,并对环进行缩点,重新编号。
4、更新其他点到环上的点的距离,如:
环中的点有(Vk1,Vk2,… ,Vki)总共i个,用缩成的点叫Vk替代,则在压缩后的图中,其他所有不在环中点v到Vk的距离定义如下:gh[v][Vk]=min { gh[v][Vkj]-mincost[Vkj] } (1<=j<=i)
而Vk到v的距离为 gh[Vk][v]=min { gh[Vkj][v] } (1<=j<=i)
5、重复3,4知道没有环为止。
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> using namespace std; const double inf=1e10; #define maxn 1010 #define maxm 40010 /* * 最小树形图 * int型 * 复杂度O(NM) * 点总0开始 */ struct Edge { int u,v; double cost; }; Edge edge[maxm]; int pre[maxn],id[maxn],vis[maxn]; double in[maxn]; double zhuliu(int root,int n,int m,Edge edge[]) { int u,v,i; double res=0; while(1) { for(i=0;i<n;i++) in[i]=inf; for(i=0;i<m;i++) if(edge[i].u!=edge[i].v && edge[i].cost<in[edge[i].v]) { pre[edge[i].v]=edge[i].u; in[edge[i].v]=edge[i].cost; } /* for(i=0;i<n;i++) if(i!=root && in[i]==inf) return -1;//不存在最小树形图*/ int tn=0;//记录有向环的数量 memset(id,-1,sizeof(id)); memset(vis,-1,sizeof(vis)); in[root]=0; for(i=0;i<n;i++) { res+=in[i]; v=i; while(vis[v]!=i && id[v]==-1 && v!=root) vis[v]=i,v=pre[v]; if(v!=root && id[v]==-1) { for(u=pre[v];u!=v;u=pre[u]) id[u]=tn; id[v]=tn++; } } if(tn==0)//当前图中不再存在环了 break; for(i=0;i<n;i++) if(id[i]==-1) id[i]=tn++; for(i=0;i<m;) { v=edge[i].v; edge[i].u=id[edge[i].u]; edge[i].v=id[edge[i].v]; if(edge[i].u!=edge[i].v) edge[i++].cost-=in[v]; else swap(edge[i],edge[--m]); } n=tn; root=id[root]; } return res; } int num[maxn],flag[maxn]; double a[maxn]; int main(void) { double v,ans; int n,m,i,j,x,y,m1; while(scanf("%d",&n)!=EOF) { ans=0;int cnt=0;m=0; memset(flag,0,sizeof(flag)); for(i=0;i<n;i++) { scanf("%lf%d",&v,&x); if(x==0) continue; flag[i]=++cnt; edge[m].u=0; edge[m].v=cnt; edge[m++].cost=v; a[cnt]=v;num[cnt]=x-1; } n=cnt+1; scanf("%d",&m1); for(i=1;i<=m1;i++) { scanf("%d%d%lf",&x,&y,&v); x--;y--; if(flag[x]==0 || flag[y]==0) continue; edge[m].u=flag[x]; edge[m].v=flag[y]; edge[m++].cost=v; a[flag[y]]=min(a[flag[y]],v); } for(i=1;i<=cnt;i++) ans+=a[i]*num[i]; printf("%.2f\n",ans+zhuliu(0,n,m,edge)); } return 0; } /* 3 10.00 1 1.80 1 2.50 2 2 1 3 2.00 3 2 1.50 */
相关文章推荐
- UVA11865[Stream My Contest] 朱刘算法求最小树形图
- poj3164 Command Network 最小树形图-朱刘算法
- UVa11183 Teen Girl Squad, 最小树形图,朱刘算法
- 图论--最小树形图朱刘算法模板
- 最小树形图/朱刘算法……表示稍微记录一下
- hdu 4009 最小树形图模板题朱刘算法
- 【TOJ】2248 Channel Design 最小树形图——朱刘算法
- 最小树形图 朱刘算法
- HDU 2121 Ice_cream’s world II 无固定点的最小树形图 朱刘算法
- 【POJ】3164 Command Network 最小树形图——朱刘算法
- 最小树形图 模版--朱刘算法
- 最小树形图(朱刘算法模板)
- 最小树形图模板朱刘算法分享
- 【POJ3164】Command Network 最小树形图 朱刘算法
- poj3164(最小树形图&朱刘算法模板)
- POJ 3164 Command Network (最小树形图-朱刘算法)
- (最小树形图 朱刘算法) poj 3164
- POJ 3164 最小树形图 朱刘算法
- POJ3164 最小树形图 有向图的最小生成树 模板题 朱刘算法 朱永津-刘振宏算法
- 最小树形图(朱刘算法模板)