题目:

  点这里OvO http://acm.hdu.edu.cn/showproblem.php?pid=6041

  2017 Multi-University Training Contest - Team 1 - 1009    

题解:

  1.由于每条边只在一个环中,每个环必然要拿掉一条边,而这些边都是不重复的,那么最小生成树就对应的是通过求每个环中拿掉一条边,总和最大的组合对应的剩下的树(第k小生成树对应第k大组合剩下的树)。xjbdfs搜一下环,把每个环中的点放到一个集合中。

  2.然后对集合排序,xjb利用优先队列 ( 要注意优先队列中的元素的数量要保持和新集合的元素个数相同,以降低时间复杂度 ) 求最大的k(如果总数没k个那就不是k个)个组合(每个集合中取一个元素的组合)

 #include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue> using namespace std; typedef long long ll; const int N=1e4+;
const int M=2e3+;
const ll mod=(ll)pow(,); struct node{
int u,v,d;
int next;
}edge[*N]; struct NODE
{
int v,now; //value is (v), now add with (now)
friend bool operator<(NODE x,NODE y)
{
return x.v < y.v;
}
};//small to big priority_queue<NODE> Q;
int num;
int head[N];
int n,m,k;
ll ans;
int snum;
int stk[N],lstk;
bool instk[M];
vector<int> s[N];
int val[M][M];
vector<int> f,tmpf;
ll sum_of_edge;
ll du[M]; bool cmp(int a,int b)
{
return a>b;
} void addedge(int u,int v,int d)
{
edge[num].u=u;
edge[num].v=v;
edge[num].d=d;
edge[num].next=head[u];
head[u]=num++;
} void init()
{
num=; //记得初始化
memset (head,-,sizeof(head));
memset(du,,sizeof(du));
snum=;
lstk=;
memset(instk,,(n+)*sizeof(bool));
for(int i=;i<=n;i++)
s[i].clear();
ans=;
sum_of_edge=;
} void dfs(int rt,int fa)
{
int v;
if(instk[rt])
{
snum++;
int sav=rt;
int sav_lstk=lstk;
while(stk[lstk]!=rt)
{
s[snum].push_back(val[sav][stk[lstk]]);
sav=stk[lstk--];
}
s[snum].push_back(val[sav][stk[lstk]]);
lstk=sav_lstk;
return ;
}
instk[rt]=;
stk[++lstk]=rt;
for(int i=head[rt];i!=-;i=edge[i].next)
{
v=edge[i].v;
if(v==fa || du[v]==) continue;
du[rt]--; du[v]--;
dfs(v,rt);
}
instk[rt]=;
lstk--;
} void merge()
{
NODE q;
int i,j,cnt;
f.clear();
if(snum==)
{
f.push_back();
return ;
}
for(int i=;i<s[].size();i++)
f.push_back(s[][i]);
for(int i=;i<=snum;i++)
{
cnt=f.size()*s[i].size();
if(cnt>k) cnt=k;
while(!Q.empty())
Q.pop();
for(j=;j<s[i].size();j++)
{
q.v=s[i][j]+f[];
q.now=;
Q.push(q);
}
tmpf.clear();
while(cnt--)
{
q=Q.top();
Q.pop();
tmpf.push_back(q.v);
if(q.now!=f.size()-)
{
q.v-=f[q.now];
q.now++;
q.v+=f[q.now];
Q.push(q);
}
}
swap(f,tmpf);
}
// cout<<"check merge\n";
// for(int i=0;i<f.size();i++)
// printf("%d ",f[i]);
// printf("\n");
// printf("end of check of merge\n");
} void solve()
{
dfs(,-);
for(int i=;i<=snum;i++)
sort(s[i].begin(),s[i].end(),cmp);
// printf("check s\n");
// for(int i=1;i<=snum;i++)
// {
// for(int j=0;j<s[i].size();j++)
// printf("%d",s[i][j]);
// printf("\n");
// }
// printf("end of check of s\n");
merge();
} int main()
{
int cas=,a,b,c;
while(scanf("%d%d",&n,&m)!=EOF)
{
init();
for(int i=;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&c);
addedge(a,b,c);
addedge(b,a,c);
du[a]++; du[b]++;
val[a][b]=val[b][a]=c;
sum_of_edge+=c;
}
scanf("%d",&k);
solve();
for(int i=;i<f.size();i++)
ans=(ans+1ll*(i+)*(sum_of_edge-f[i])%mod)%mod;
printf("Case #%d: %lld\n",++cas,ans%mod);
}
return ;
}

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(二分+搜索)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=6041 [题目大意] 给出一个仙人掌图,求第k小生成树 [题解] 首先找到仙人掌图上的环,现在的问题 ...

  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 - 6041:I Curse Myself(Tarjan求环&K路归并)

    There is a connected undirected graph with weights on its edges. It is guaranteed that each edge app ...

  8. HDU 2520 我是菜鸟,我怕谁

    我是菜鸟,我怕谁 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Su ...

  9. HDU 5433 Xiao Ming climbing 动态规划

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5433 Xiao Ming climbing Time Limit: 2000/1000 MS (Ja ...

随机推荐

  1. 【1.1】mysql frm文件丢失(ibd文件丢失)

    [1]故障模拟准备环境 这里以innodb为例 [1.1]配置参数 开启独立表空间 innodb_file_per_table; [1.2]构建测试数据 create database test; c ...

  2. MySQL_bigint(20) 是什么意思?

    MySQL_bigint(20) 是什么意思? MySQL的整型类型有这样几种:   类型 存储空间 M默认值(显示宽度) 数据大小(无符号:unsigned) 描述 1 tinyint(M) 1 t ...

  3. PHP以table形式导出数据表实现单元格内换行

    <br style='mso-data-placement:same-cell;'>

  4. spark教程(八)-SparkSession

    spark 有三大引擎,spark core.sparkSQL.sparkStreaming, spark core 的关键抽象是 SparkContext.RDD: SparkSQL 的关键抽象是 ...

  5. T100——读取系统程序临时表数据

    SELECT   * FROM   USER_OBJECTS ORDER  BY  CREATED DESC SELECT   * FROM   USER_OBJECTS WHERE  OBJECT_ ...

  6. Codeforces 1238G. Adilbek and the Watering System

    传送门 最关键的想法就是每个位置一定用的是当前能用的最便宜的水,因为到后面可能有更便宜的 然后其他还没用上的水我们也留着,假装此时已经买了,但是如果发现后面有更优的再反悔也不迟 每相邻两个朋友之间我们 ...

  7. hdu 1215 求约数和 唯一分解定理的基本运用

    http://acm.hdu.edu.cn/showproblem.php?pid=1215 题意:求解小于n的所有因子和 利用数论的唯一分解定理. 若n = p1^e1 * p2^e2 * ……*p ...

  8. Maven maven-compiler-plugin 编译问题

    问题:每次右键项目名-maven->update project 时候,项目jdk版本变了,变回1.5版本或者其他版本 解决方案一:修改maven的配置(解压目录的conf\setting.xm ...

  9. Eclipse怎么改变@author 姓名

    1 点击windows  然后选择 点击进去选择搜索code Templates  点击选择出现下面的页面 点开comments,里面有给方法,变量 ,类等加注释设置的模板 如:点击Methods  ...

  10. Linux Permission denied 问题

    Linux Permission denied 问题 来源  https://www.cnblogs.com/sparkdev/p/10287164.html 如果当前用户没有某个文件的写权限,又要通 ...