最小树形图/朱刘算法……表示稍微记录一下
来源:互联网 发布:淘宝网店加盟电话 编辑:程序博客网 时间:2024/05/17 02:56
大概就是那么几步……呃…
1) 每个点找到权值最小的入边,记录为In[i];
2) 【假装是一只定根的图】判有无除了根节点之外的独立节点,如果有的话那这个图必然不连通 于是直接return -1
3) 然后开始找环,至于在这种有n条边的图上找环的事,参考noip2015提高组D1T2
4) 找环的时候顺手把环缩了(标记一下,创建新的节点)
5) 然后更新 新图 的每个节点之间的距离,于是就会出现下面这种鬼畜的东西↓↓↓
说明一下为什么出边的权不变,入边的权要减去in [u]。对于新图中的最小树形图T,设指向人工节点的边为e。将人工节点展开以后,e指向了一个环。假设原先e是指向u的,这个时候我们将环上指向u的边 in[u]删除,这样就得到了原图中的一个树形图。我们会发现,如果新图中e的权w'(e)是原图中e的权w(e)减去in[u]权的话,那么在我们删除掉in[u],并且将e恢复为原图状态的时候,这个树形图的权仍然是新图树形图的权加环的权,而这个权值正是最小树形图的权值。所以在展开节点之后,我们得到的仍然是最小树形图。逐步展开所有的人工节点,就会得到初始图的最小树形图了。 ——摘自百度百科 最小树形图(看代码看不懂的那一段
关于为什么 在给点重新编号的时候,计算每个新的点之间的距离 是这样奇怪的公式
假设是点i到点集vj(也就是新点vj)的距离,vj由n个点组成(vj1,vj2,vj3.....vjn)
dis[i][vj]=min{dis[i][vjk]-in[vik]}(1<=k<=n)
但是点集vj到点i的距离却是
dis[vj][i]=min{dis[vjk][i]}(1<=k<=n)
相当于是每条边都减去它指向的那个点的最小入边长度(如果这条边两边的点不在同一个集合中的话)
6) 最后,默默表示,细节什么的,真的,很重要 orzorzorz,用左闭右开区间,【左闭右闭WA到半夜一点的某表示……对自己的信仰产生了怀疑
最后附上呆马,虽然丑哭了,也许还会又WA又T又RE
题目在……呃……这里的learn那道题
#include<cstdio>#include<algorithm>#include<cstring>using namespace std;int n,m;int S=0;const int INF=0x3f3f3f3f;int aim[55];int num[55],cnt_node=1;struct t1{int frm,to,nxt,lth;}edge[10057];int cnt_edge=0;int fst[557];void addedge(int x,int y,int z){edge[++cnt_edge].to=y;edge[cnt_edge].frm=x;edge[cnt_edge].nxt=fst[x];edge[cnt_edge].lth=z;fst[x]=cnt_edge;}void init(){for(int i=1;i<=n;++i){for(int j=num[i]+1;j<num[i+1];++j)addedge(j,j-1,0);addedge(num[n+1],num[i],0);}while(m--){int a,b,c,d,e;scanf("%d%d%d%d%d",&a,&b,&c,&d,&e);addedge(num[a]+b,num[c]+d,e);}}//========================================================================int ans=0;int col[557];int cnt_col;int pre[557];int In[557];int vis[557];int zhuliu(int root,int NE,int NV){for(;;){memset(In,INF,sizeof(In));memset(pre,-1,sizeof(pre));//初始化每个点的Infor(int i=1;i<=NE;++i)if(edge[i].lth<In[edge[i].to]&&edge[i].to!=edge[i].frm)In[edge[i].to]=edge[i].lth,pre[edge[i].to]=edge[i].frm;//判有没有独立节点for(int i=0;i<NV;++i){if(i==root)continue;if(In[i]==INF)return -1;}//判环,缩环 cnt_col=0;memset(vis,-1,sizeof(vis));memset(col,-1,sizeof(col));In[root]=0;for(int i=0;i<NV;++i){ans+=In[i];int now=i;while(vis[now]!=i&&col[now]==-1&&now!=root){vis[now]=i;now=pre[now];}if(now!=root&&!(~col[now])){for(int tmp=pre[now];tmp!=now;tmp=pre[tmp])col[tmp]=cnt_col;col[now]=cnt_col++;}}//如果没有环就表示,树建好啦 if(!cnt_col)return ans;//给节点标新序号 for(int i=0;i<NV;i++) if(!(~col[i]))col[i]=cnt_col++;//按照 入边长度-=In[i] 的规则更新每个新节点之间的距离for(int i=1;i<=NE;++i){int tt=edge[i].to;edge[i].frm=col[edge[i].frm];edge[i].to=col[edge[i].to];if(edge[i].frm!=edge[i].to)edge[i].lth-=In[tt];}NV=cnt_col;root=col[root];}}int main(){memset(fst,0,sizeof(fst));memset(edge,0,sizeof(edge));num[0]=0;while(scanf("%d%d",&n,&m)!=EOF&&(n||m)){for(int i=1;i<=n;++i)scanf("%d",&aim[i]),++aim[i],num[i+1]=num[i]+aim[i];init();printf("%d\n",zhuliu(num[n+1],cnt_edge,num[n+1]+1));}return 0;}
- 最小树形图/朱刘算法……表示稍微记录一下
- 最小树形图(刘朱算法)记录
- 最小树形图(刘朱算法)
- 最小树形图 模版--朱刘算法
- 最小树形图(朱-刘算法)
- 最小树形图(朱-刘算法)
- hdu4966 最小树形图 /刘朱算法
- 最小树形图 朱刘算法
- 最小树形图(朱-刘算法)
- 最小树形图 朱刘算法
- 最小树形图(朱刘算法)
- 最小树形图-朱刘算法
- 最小树形图 朱刘算法【转载】
- 最小树形图(朱-刘算法)
- BZOJ 4349: 最小树形图(最小树形图->朱刘算法)
- bzoj4349&2260 最小树形图(商店购物)(朱刘算法 最小树形图)
- 朱、刘算法:求最小树形图权值个人理解+个人详解【最小树形图模板】
- 朱、刘算法:求最小树形图权值个人理解+个人详解【最小树形图模板】
- python爬虫之正则表达式
- 求n的阶乘
- gradle
- iOS多线程的初步研究(三)-- NSRunLoop
- vbscript基础2
- 最小树形图/朱刘算法……表示稍微记录一下
- Java中的赋值问题
- 导入JavaEE5 library
- [JSOI2007] [BZOJ1031] 字符加密Cipher - 后缀数组
- mybatis与spring的整合
- Android selector的item里的属性说明
- csdn知识库网址
- JavaScriptCore框架在iOS7中的对象交互和管理
- 二分查找 2016.3.17