HDU2121 Ice_cream’s world II【最小树形图】
2017-08-18 16:07
381 查看
题意:一个有向图,选一个根节点,使他能到所有点,费用最小
思路:无固定根最小树形图,我们建一个超级根,连接所有点,边权为 原有边权和sum+1,这样子设边权,是因为最后判断的时候如果ans-sum-1 大于 sum的话,也是无解的。原来的边权和sum,现在减去一条边后,比它还大,就说明从超级根,连下来不只一条,不符合题意。
记录是哪个点的话,记录边的位置(新建的边在之后建,减原来的边数m,就是连的那个点)。
为什么不直接记录 ansi = edge[i].v 呢
在朱刘算法中,这些点会变的
思路:无固定根最小树形图,我们建一个超级根,连接所有点,边权为 原有边权和sum+1,这样子设边权,是因为最后判断的时候如果ans-sum-1 大于 sum的话,也是无解的。原来的边权和sum,现在减去一条边后,比它还大,就说明从超级根,连下来不只一条,不符合题意。
记录是哪个点的话,记录边的位置(新建的边在之后建,减原来的边数m,就是连的那个点)。
for(int 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; if(edge[i].u == root) ansi = i; } }
为什么不直接记录 ansi = edge[i].v 呢
在朱刘算法中,这些点会变的
for(int i=0;i<m;i++) { int v=edge[i].v; edge[i].u=id[edge[i].u]; // here ! edge[i].v=id[edge[i].v]; // here ! if(edge[i].u!=edge[i].v) edge[i].cost-=in[v]; }
#include<stdio.h> #include<iostream> #include<string.h> #include<string> #include<stdlib.h> #include<math.h> #include<vector> #include<list> #include<map> #include<stack> #include<queue> #include<algorithm> #include<numeric> #include<functional> using namespace std; typedef long long ll; const int maxn = 1005; const int maxm = 20005; struct Edge { int u, v; ll cost; }edge[maxm];//边集 int pre[maxn],id[maxn],vis[maxn]; ll in[maxn]; int ansi; ll zhuliu(int root,int n,int m)//返回最小花费 { ll res=0; while(true) { for(int i=0;i<n;++i) in[i]=0x3f3f3f3f3f3f3f3f; for(int 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; if(edge[i].u == root) ansi = i; } } for(int i=0;i<n;++i) if(i!=root && in[i]==0x3f3f3f3f3f3f3f3f) return -1;//不存在最小树形图 int tn=0;//新图结点数 for(int i=0;i<n;++i) { id[i]=-1; vis[i]=-1; } in[ bef7 root]=0; for(int i=0;i<n;++i) { res+=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]=tn; id[v]=tn++; } } if(tn==0)//没有有向环 break; for(int i=0;i<n;++i) if(id[i]==-1) id[i]=tn++; for(int i=0;i<m;i++) { int 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]; } n=tn; root=id[root]; } return res; } //点、边下标从0开始 void add(int i,int a,int b,ll c) { edge[i].u = a; edge[i].v = b; edge[i].cost = c; } int main(void) { int n,m; while(scanf("%d%d",&n,&m)!=EOF) { ll sum = 1; for(int i = 0; i < m; i++) { int a,b; ll c; scanf("%d%d%lld",&a,&b,&c); add(i,a,b,c); sum += c; } for(int i = 0; i < n; i++) add(m+i,n,i,sum); ll ans = zhuliu(n,n+1,m+n); if(ans == -1 || ans-sum >= sum) printf("impossible\n\n"); else printf("%lld %d\n\n",ans-sum,ansi-m); } return 0; }
相关文章推荐
- hdu2121 Ice_cream’s world II (最小树形图模板)
- HDU2121 Ice_cream’s world II【最小树形图】【不定根】
- HDU2121 Ice_cream’s world II 【最小树形图】+【不定根】
- kuangbin专题八 HDU2121 Ice_cream’s world II(不定根的最小树形图)
- HDU2121-Ice_cream’s world II(最小树形图)
- HDU 2121 Ice_cream’s world II 最小树形图 模板
- HDU ACM 2121 Ice_cream’s world II (无根最小树形图)
- 不定根最小树形图 Ice_cream’s world II HDU - 2121
- HDU 2121 Ice_cream’s world II(无固定根最小树形图、找最小根)
- HDU 2121 Ice_cream’s world II 不定根最小树形图
- HDU 2121——Ice_cream’s world II——————【最小树形图、不定根】
- hdu 2121 Ice_cream’s world II(最小树形图,不定根)
- HDU 2121 Ice_Cream's World II (最小树形图)
- Ice_cream’s world II - HDU 2121 - 最小树形图
- HDU 2121 Ice_cream’s world II(最小树形图)
- HDU 2121 Ice_cream’s world II 无固定点的最小树形图 朱刘算法
- hdoj 2121 Ice_cream’s world II 【虚拟源点求无根树的最小树形图】
- HDU 2121 Ice_cream’s world II 不定根最小树形图
- HDOJ 2121 Ice_cream’s world II 最小树形图无根树
- hdu 2121 Ice_cream’s world II(无固定根最小树形图)