【题目链接】 http://acm.hdu.edu.cn/showproblem.php?pid=6041

【题目大意】

  给出一个仙人掌图,求第k小生成树

【题解】

  首先找到仙人掌图上的环,现在的问题就是从每个环中删除一个元素,
  求出删除元素总和中的第K大,我们发现通过限定第K大的大小,可以有效地搜索剪枝,
  限制的大小导致搜索出来的总和数量是具有单调性的,我们可以二分这个值,
  然后用搜索来定位第K大的大小。Thanks to Claris。

【代码】

#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;
typedef long long LL;
const int N=1010,M=2010,ALL=100010;
vector<int> v[N],w[N],a[N];
int Cas=1,n,m,K,st[N],pos,base,ans[ALL],dfn,f[N],fw[N],L,R,MID,t,cnt;
unsigned Ans;
bool cmpd(int x,int y){return x>y;}
bool cmp(const vector<int>&a,const vector<int>&b){return a[1]<b[1];}
void dfs(int x){
//printf("%d\n",x);
st[x]=++dfn;
for(int i=0;i<v[x].size();i++){
int y=v[x][i],z=w[x][i];
if(y==f[x])continue;
if(!st[y]){f[y]=x;fw[y]=z;dfs(y);}
else if(st[y]<st[x]){
a[cnt].push_back(z);
for(int j=x;j!=y;j=f[j])a[cnt].push_back(fw[j]);
sort(a[cnt].begin(),a[cnt].end(),cmpd);
base-=a[cnt][0];
for(int j=a[cnt].size()-1;~j;j--)a[cnt][j]=a[cnt][0]-a[cnt][j];
cnt++;
}
}
}
void dfs2(int x,int s){
if(pos>=K||x==cnt)return;
if(s+a[x][1]>MID)return;
for(int i=1;i<a[x].size();i++){
int sum=s+a[x][i];
if(sum>MID)break;
if(pos>=K)return;
ans[++pos]=sum;
dfs2(x+1,sum);
}dfs2(x+1,s);
}
int cal(){
LL ans=1;
for(int i=0;i<cnt;i++){
ans*=a[i].size();
if(ans>1000000)return 1000000;
}return ans;
}
int main(){
while(~scanf("%d%d",&n,&m)){
while(m--){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
v[x].push_back(y); v[y].push_back(x);
w[x].push_back(z); w[y].push_back(z);
base+=z;
}dfs(1);
sort(a,a+cnt,cmp);
scanf("%d",&K);
K=min(K,cal());
L=0,R=1000000000;
while(L<=R){
MID=(L+R)>>1; pos=1;
dfs2(0,0);
if(pos>=K)R=(t=MID)-1;
else L=MID+1;
}MID=t-1;
pos=0;
if(MID>=0)ans[++pos]=0;
dfs2(0,0);
for(int i=pos+1;i<=K;i++)ans[i]=t;
sort(ans+1,ans+K+1);
for(int i=1;i<=K;i++){
ans[i]+=base;
Ans+=1U*ans[i]*i;
}printf("Case #%d: %u\n",Cas++,Ans);
for(int i=1;i<=n;i++)f[i]=fw[i]=st[i]=0;
for(int i=0;i<cnt;i++)a[i].clear();
for(int i=1;i<=n;i++)v[i].clear(),w[i].clear();
dfn=base=Ans=cnt=0;
}return 0;
}

HDU 6041 I Curse Myself(二分+搜索)的更多相关文章

  1. HDU 6041 - I Curse Myself | 2017 Multi-University Training Contest 1

    和题解大致相同的思路 /* HDU 6041 - I Curse Myself [ 图论,找环,最大k和 ] | 2017 Multi-University Training Contest 1 题意 ...

  2. HDU 6041.I Curse Myself 无向仙人掌图

    I Curse Myself Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) ...

  3. hdu 6041 I Curse Myself

    题目: 点这里OvO http://acm.hdu.edu.cn/showproblem.php?pid=6041 2017 Multi-University Training Contest - T ...

  4. hdu 6041 I Curse Myself 无向图找环+优先队列

    I Curse Myself Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) ...

  5. HDU 6041 I Curse Myself(点双联通加集合合并求前K大) 2017多校第一场

    题意: 给出一个仙人掌图,然后求他的前K小生成树. 思路: 先给出官方题解 由于图是一个仙人掌,所以显然对于图上的每一个环都需要从环上取出一条边删掉.所以问题就变为有 M 个集合,每个集合里面都有一堆 ...

  6. HDU 6041 I Curse Myself ——(仙人掌图,tarjan,转化)

    题解见这个博客:http://blog.csdn.net/ME495/article/details/76165039. 复杂度不太会算..这个经典问题的解法需要注意,维护队列里面只有k个元素即可.另 ...

  7. HDU 1312 Red and Black --- 入门搜索 BFS解法

    HDU 1312 题目大意: 一个地图里面有三种元素,分别为"@",".","#",其中@为人的起始位置,"#"可以想象 ...

  8. HDU 1312 Red and Black --- 入门搜索 DFS解法

    HDU 1312 题目大意: 一个地图里面有三种元素,分别为"@",".","#",其中@为人的起始位置,"#"可以想象 ...

  9. hdu 3433 A Task Process 二分+dp

    A Task Process Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

随机推荐

  1. Everything Has Changed(HDU6354+圆交+求周长)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6354 题目: 题意:用一堆圆来切割一个圆心为原点,半径为R的圆A,问切割完毕后圆A外围剩余部分的周长( ...

  2. 关于auto-keras训练cnn模型

    # 我在训练自己的人脸分类模型的时候发现图片的维度不能太高,经过很多次测试过后觉得一般人脸图片分为28*28大小训练的效果比较好.建议在使用其训练自己的物体识别模型的时候,尽量把图片压缩到28*28# ...

  3. 【HNOI】d 最小割

    [题目大意]给定一个n*m的土地,每块可以种a或b作物,每种作物在不同的位置有不同的收成,同时,有q个子矩阵中,全部种指定的作物(a或b)会有一定的加成收成,求最大收成. [数据范围] 50% n,m ...

  4. 安全测试===sqlmap(贰)转载

    十二.列举数据 这些参数用于列举出数据库管理系统信息.数据结构和数据内容. 1.一键列举全部数据 参数:--all 使用这一个参数就能列举所有可访问的数据.但不推荐使用,因为这会发送大量请求,把有用和 ...

  5. 移动端测试===Android内存泄露和GC机制(转)

    本文转自:https://www.testwo.com/article/1153 1.前言 Hello,小伙伴们,相信大家在项目测试中都遇到过内存泄露问题,小编也着实爬过很多坑.比如小编所测项目,更换 ...

  6. 获取并编译最新的Notepad++源码

    获取并编译最新的Notepad++源码 http://blog.csdn.net/u012814856/article/details/68947310 Notepad++源码编译及其分析 http: ...

  7. c++ 引用的分析

    在一般教材里面,我们会说引用是变量的别名,另外在 c++ primer 5里面说到引用的时候,说引用不是对象,不能对它进行取地址.但是我们来看看下面代码的分析: #include <iostre ...

  8. 取消div,a等标签点击效果

    当标签被设置onclick事件之后,在有些手机浏览器中,点击这些标签,会有点击变色效果.想要取消点击变色效果. 添加:div{-webkit-tap-highlight-color:rgba(0,0, ...

  9. Fel表达式计算引擎学习

    转载原文地址:Fel是轻量级的高效的表达式计算引擎 Fel的问题 Fel的问题 Fel是轻量级的高效的表达式计算引擎 Fel在源自于企业项目,设计目标是为了满足不断变化的功能需求和性能需求. Fel是 ...

  10. svn命令行

    svn查看某一版本下的某一文件 svn cat -r 版本号 文件的目录 svn 对比两个版本之间的差别 svn diff -r 新版本:旧版本