题目:

  点这里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 ;
}

最新文章

  1. iOS 3D Touch实践
  2. 学习js回调函数
  3. 两个实用的方法从Base64字符串生成RSAPublicKey及RSAPrivatekey
  4. topcoder SRM 610 DIV2 TheMatrix
  5. iOS学习笔记---oc语言第一天
  6. CSS控制div宽度最大宽度/高度和最小宽度/高度
  7. nodejs5-package.json
  8. MVC中Razor视图基本语法(1)
  9. python 网络编程第一版
  10. H5使用codovar插件实现支付宝支付(支付宝APP支付模式,前端)
  11. ES6学习笔记六(Iterator和for..of)
  12. Centos7在单用户模式下重置root密码
  13. wamp升级php5.3.10到5.4.31版本
  14. MySQL主从复制介绍
  15. js 设计模式——观察者模式
  16. awk基础01-基本用法
  17. 基于 od 窗口的anti
  18. linux shell每天一阅 -- 安装nginx以及apache
  19. Python基础(1)_初识Python
  20. POJ——1308Is It A Tree?(模拟拓扑排序判断有向图是否为树)

热门文章

  1. [转帖]Nginx 容器教程
  2. win10的修改hosts文件
  3. T100——上传图片
  4. nginx部署vue前端,刷新出现404或者500错误的解决方案
  5. QByteArray详解
  6. Django: ORM 数据库设置和读写分离
  7. 如何调试Python程序 通过IDLE
  8. O040、Migrate Instance 操作详解
  9. postman传数组参数,二维数组,多维数组
  10. javascript的隐式类型转换(使(a==1&amp;&amp;a==2&amp;&amp;a==3) 成立)