hdu2121-Ice_cream’s world II
给出一个有向图,求最小树形图和它的最小的根。
分析
这个题又写了一晚上~我之前的朱刘算法写法是我乱想的,只有那道题可以过……所以去找了一份代码来看,发现我的写法超级麻烦啊,所以就学习了一下那种写法,非常漂亮,但是有一些判断要考虑。
这是一个不定根问题,经典解决方法是添加一个超级根,向每个点连一条长度大于所有边权和的边,设它为\(sum\),然后以超级根为根求最小树形图。如果最后最小树形图的答案超过了\(2sum\),那么就说明超级根至少连出去两条边,即原图不连通。如果原图连通,那么把\(sum\)减掉即可。
关键在于如何求最小的根。可以发现,如果我们从小到大把超级根到所有点的边加进去,然后在算法过程中从小到大遍历边,如果有多个\(in\)最小且从root过来的,那么我们会找到最小的那个。但是缩点怎么办呢?朱刘算法的这种写法的一个很大的好处就是保留了所有的点,只是改了它们的id,所以我们可以以边为关键搜索,如果找到第\(i\)条边为\((root,v,w)\),它是最小的,那么就把最小根更新为\(i\),那么最终的最小根就是\(i-m\),其中\(m\)为原图上的边数。非常巧妙!
代码
为什么全改giant还比只改用到的快200ms啊。
代码的几个需要注意的地方:
- 找环的时候不能把已经有id的点再给一次id
- 在内部找环的时候从上一个开始找
- 只有当原来的边的两个点不在同一个环中才能减它的边权
- 前面在处理in的时候当\(u=v\)的时候直接跳过这条边
- 现在这个写法中的无环条件为col=1
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long giant;
giant read() {
giant x=0,f=1;
char c=getchar();
for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
for (;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
const giant maxn=2e3+10;
const giant maxm=4e4+10;
const giant inf=1e8+7;
struct edge {
giant u,v,w,nxt;
};
struct graph {
edge e[maxm];
giant h[maxn],tot,in[maxn],from[maxn],id[maxn],tic[maxn],n,real,vis[maxn];
void clear(giant _n) {
memset(h,0,sizeof h),tot=0,n=_n;
}
void add(giant u,giant v,giant w) {
e[++tot]=(edge){u,v,w,h[u]};
h[u]=tot;
}
giant MTG(giant root) {
giant ret=0;
while (true) {
fill(in+1,in+n+1,inf);
memset(id,0,sizeof id);
memset(from,0,sizeof from);
memset(vis,0,sizeof vis);
for (giant i=1;i<=tot;++i) if (e[i].u!=e[i].v && in[e[i].v]>e[i].w) {
in[e[i].v]=e[i].w,from[e[i].v]=e[i].u;
if (e[i].u==root) real=i;
}
giant col=1,j;
for (giant i=1;i<=n;++i) if (i!=root) {
ret+=in[i];
for (j=i;j!=root && !id[j];j=from[j]) if (vis[j]!=i) vis[j]=i; else break;
if (j!=root && !id[j]) {
for (giant k=from[j];k!=j;k=from[k]) id[k]=col;
id[j]=col++;
}
}
if (col==1) break;
for (giant i=1;i<=n;++i) if (!id[i]) id[i]=col++;
for (giant i=1;i<=tot;++i) {
giant u=e[i].u,v=e[i].v;
e[i].u=id[u],e[i].v=id[v];
if (e[i].u!=e[i].v) e[i].w-=in[v];
}
root=id[root],n=col-1;
}
return ret;
}
} A;
int main() {
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
freopen("my.out","w",stdout);
#endif
giant n,m;
while (~scanf("%lld%lld",&n,&m)) {
A.clear(n+1);
giant sum=1;
for (giant i=1;i<=m;++i) {
giant u=read()+1,v=read()+1,w=read();
A.add(u,v,w);
sum+=w;
}
for (giant i=1;i<=n;++i) A.add(n+1,i,sum);
giant ans=A.MTG(n+1);
if ((ans-=sum)>=sum) puts("impossible\n"); else
printf("%lld %lld\n\n",ans,A.real-m-1);
}
}
hdu2121-Ice_cream’s world II的更多相关文章
- hdu2121 Ice_cream's world II
hdu2121 Ice_cream's world II 给一个有向图,求最小树形图,并输出根节点 \(n\leq10^3,\ m\leq10^4\) 最小树形图 对于求无根最小树形图,可以建一个虚拟 ...
- HDU2121 Ice_cream’s world II —— 最小树形图 + 不定根 + 超级点
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2121 Ice_cream’s world II Time Limit: 3000/1000 MS (J ...
- hdu2121 - Ice_cream’s world II(朱刘算法,不固定根)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2121 题目意思大概是要你在一些城市中选一个做首都 , 要求首都都能到其他城市 , 道路花费要最少 , ...
- hdu2121 Ice_cream’s world II 最小树形图(难)
这题比HDU4009要难一些.做了4009,大概知道了最小树形图的解法.拿到这题,最直接的想法是暴力.n个点试过去,每个都拿来做一次根.最后WA了,估计是超时了.(很多题都是TLE说成WA,用了G++ ...
- HDU2121 Ice_cream’s world II (最小树形图)
在建图的时候对原图进行加边 建立一个超级源点~ #include<cstdio> #include<algorithm> #include<cstring> usi ...
- HDU2121:Ice_cream’s world II (虚根+有向图最小生成树)
Ice_cream’s world II Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Oth ...
- 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 ...
- hdoj 2121 Ice_cream’s world II 【没有最低树的根节点】
称号:pid=2121" target="_blank">hdoj 2121 Ice_cream's world II 题意:题目是一道躶题,给n个点,m条边的有向 ...
- HDU 2121 Ice_cream’s world II 最小树形图 模板
开始学习最小树形图,模板题. Ice_cream’s world II Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32 ...
- 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 ...
随机推荐
- .net core 基于multipart/form-data的文件上传,这里以图片上传为例
首先传递的数据格式大概如下: 然后就可以在后端获取数据了:直接上代码了哈: [HttpPost] ///分别获取 data数据和调用图片上传方法 public async Task< ...
- linux-flock文件锁之实际运用
vi test.sh #! /bin/bash echo "Hello World" touch test.lock #随便命名 [root@localhost ~]# flock ...
- 用CRF做命名实体识别(二)
用CRF做命名实体识别(一) 用CRF做命名实体识别(三) 一. 摘要 本文是对上文用CRF做命名实体识别(一)做一次升级.多添加了5个特征(分别是词性,词语边界,人名,地名,组织名指示词),另外还修 ...
- Java子类与父类之间的类型转换
1.向上转换 父类的引用变量指向子类变量时,子类对象向父类对象向上转换.从子类向父类的转换不需要什么限制,只需直接蒋子类实例赋值给父类变量即可,这也是Java中多态的实现机制. 2.向下转换 在父类变 ...
- Java: Replace a string from multiple replaced strings to multiple substitutes
Provide helper methods to replace a string from multiple replaced strings to multiple substitutes im ...
- java 二叉树的创建 遍历
本来说复习一下BFS和DFS,辗转就来到了二叉树...本文包括二叉树的创建和遍历 概念 数据:1 2 3 4 5 6 7生成一颗二叉树 上面的数是数据,不是位置,要区别一下数据和位置 红色的代表位置, ...
- 「日常训练」Kefa and Company(Codeforces Round #321 Div. 2 B)
题意与分析(CodeForces 580B) \(n\)个人,告诉你\(n\)个人的工资,每个人还有一个权值.现在从这n个人中选出m个人,使得他们的权值之和最大,但是对于选中的人而言,其他被选中的人的 ...
- Linux用户及权限
库:lib 共享库:.so ,shared object, 权限: 用户,获取资源,服务的标识符 组,指派权限,标识符 进程:以某个用户的身份在进行,有属主和属组 安全上下文(security con ...
- 域名、IP地址、URL关系
域名是个文字形式记录的IP地址 IP地址是计算机在网络中的门牌号! URL是网页地址 例如1: http://zhidao.baidu.com/question/14674128.html 是URL ...
- JavaScript 字符串 & Math & Date
字符串 字符串就是零个或多个排在一起的字符,放在单引号或双引号之中. 'abc' "abc" 单引号字符串的内部,可以使用双引号.双引号字符串的内部,可以使用单引号. 'key=& ...