hdu 6041 I Curse Myself 无向图找环+优先队列
Posted xjhz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 6041 I Curse Myself 无向图找环+优先队列相关的知识,希望对你有一定的参考价值。
I Curse Myself
Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Problem Description
There is a connected undirected graph with weights on its edges. It is guaranteed that each edge appears in at most one simple cycle.
Assuming that the weight of a weighted spanning tree is the sum of weights on its edges, define V(k) as the weight of the k-th smallest weighted spanning tree of this graph, however, V(k) would be defined as zero if there did not exist k different weighted spanning trees.
Please calculate (∑k=1Kk⋅V(k))mod232.
Assuming that the weight of a weighted spanning tree is the sum of weights on its edges, define V(k) as the weight of the k-th smallest weighted spanning tree of this graph, however, V(k) would be defined as zero if there did not exist k different weighted spanning trees.
Please calculate (∑k=1Kk⋅V(k))mod232.
Input
The input contains multiple test cases.
For each test case, the first line contains two positive integers n,m (2≤n≤1000,n−1≤m≤2n−3), the number of nodes and the number of edges of this graph.
Each of the next m lines contains three positive integers x,y,z (1≤x,y≤n,1≤z≤106), meaning an edge weighted z between node x and node y. There does not exist multi-edge or self-loop in this graph.
The last line contains a positive integer K (1≤K≤105).
For each test case, the first line contains two positive integers n,m (2≤n≤1000,n−1≤m≤2n−3), the number of nodes and the number of edges of this graph.
Each of the next m lines contains three positive integers x,y,z (1≤x,y≤n,1≤z≤106), meaning an edge weighted z between node x and node y. There does not exist multi-edge or self-loop in this graph.
The last line contains a positive integer K (1≤K≤105).
Output
For each test case, output "Case #x: y" in one line (without quotes), where x indicates the case number starting from 1 and y denotes the answer of corresponding case.
Sample Input
4 3
1 2 1
1 3 2
1 4 3
1
3 3
1 2 1
2 3 2
3 1 3
4
6 7
1 2 4
1 3 2
3 5 7
1 5 3
2 4 1
2 6 2
6 4 5
7
Sample Output
Case #1: 6
Case #2: 26
Case #3: 493
Source
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #include<set> #include<map> #include<queue> #include<stack> #include<vector> using namespace std; #define PI acosI(-1.0) typedef long long ll; typedef pair<int,int> P; const int maxn=1e3+100,maxm=1e5+100,inf=0x3f3f3f3f,mod=1e9+7; const ll INF=1e13+7; struct is { int x,r; bool operator <(const is &c)const { return x<c.x; } }; int d[maxn],n,m,k; inline void update(vector<int>&a,vector<int>&b) { priority_queue<is>q; for(int i=0;i<b.size();i++) d[i] = 0,q.push((is){a[0]+b[i],i}); vector<int>ans; for(int i=1;i<=k;i++) { if(q.empty())break; is x=q.top(); q.pop(); ans.push_back(x.x); if(d[x.r]+1<a.size()) q.push((is){a[++d[x.r]]+b[x.r],x.r}); } a=ans; } int cmp(int x,int y) { return x>y; } struct edge { int from,to,d,nex; }G[maxn<<2]; int head[maxn],edg; inline void addedge(int u,int v,int d) { G[++edg]=(edge){u,v,d,head[u]},head[u]=edg; G[++edg]=(edge){v,u,d,head[v]},head[v]=edg; } int pre[maxn],bccno[maxn]; int dfs_clock,bcc_cnt; stack<int>s; vector<int>ans,fuck; inline int dfs(int u,int fa) { int lowu=++dfs_clock; pre[u]=dfs_clock; int child=0; for(int i=head[u]; i!=-1; i=G[i].nex) { int v=G[i].to; edge e=G[i]; if(!pre[v]) { s.push(i); child++; int lowv=dfs(v,u); lowu=min(lowu,lowv); if(lowv>=pre[u]) { bcc_cnt++; fuck.clear(); while(true) { int e=s.top(); s.pop(); fuck.push_back(G[e].d); if(bccno[G[e].from]!=bcc_cnt) bccno[G[e].from]=bcc_cnt; if(bccno[G[e].to]!=bcc_cnt) bccno[G[e].to]=bcc_cnt; if(G[e].from==u&&G[e].to==v) break; } if(fuck.size()>1)update(ans,fuck); } } else if(pre[v]<pre[u]&&v!=fa) { s.push(i); lowu=min(lowu,pre[v]); } } return lowu; } void init() { dfs_clock=bcc_cnt=edg=0; for(int i=0;i<=n;i++) head[i]=-1,bccno[i]=0,pre[i]=0; ans.clear(); ans.push_back(0); } int main() { int cas=1; while(scanf("%d%d",&n,&m)!=EOF) { init(); ll sumsum=0; for(int i=1; i<=m; i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); sumsum+=z; addedge(x,y,z); } scanf("%d",&k); dfs(1,-1); ll out=0,MOD=(1LL<<32); printf("Case #%d: ",cas++); for(int i=1;i<=k;i++) { if(i-1>=ans.size())break; out+=1LL*(sumsum-ans[i-1])*i; out%=MOD; } printf("%lld\n",out); } return 0; }
以上是关于hdu 6041 I Curse Myself 无向图找环+优先队列的主要内容,如果未能解决你的问题,请参考以下文章
HDU 6041.I Curse Myself 无向仙人掌图
6041 I Curse Myself(点双联通加集合合并求前K大) 2017多校第一场
icpc2018焦作Mathematical Curse(动态规划)