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.
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).
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
解法:
Tarjan找环,然后运行K路归并,这个模型在白书的190页上有例题。下面提到的暴力O(MK)的并不会。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e3+7;
const int maxm = 1e5+5;
struct edge{
int v,w,next;
}E[maxn*4];
int n,m,k,head[maxn],arr[maxm],ans[maxm],tmp[maxm],dfn[maxn],dfsclk,edgecnt;
void init(){
dfsclk=edgecnt=0;
memset(head,-1,sizeof(head));
memset(dfn,0,sizeof(dfn));
ans[0]=1;
ans[1]=0;
}
void add(int u, int v, int w){
E[edgecnt].v=v,E[edgecnt].w=w,E[edgecnt].next=head[u],head[u]=edgecnt++;
}
struct node{
int val,u,v;
node(){}
node(int val,int u,int v):val(val),u(u),v(v){}
bool operator < (const node&rhs) const{
return val<rhs.val;
}
};
void merge(int *A, int *B)
{
priority_queue<node>q;
sort(B+1, B+B[0]+1);
for(int i=1; i<=B[0]; i++) q.push(node(A[1]+B[i],1,i));
tmp[0]=0;
while(tmp[0]<k&&!q.empty()){
node x = q.top(); q.pop();
tmp[++tmp[0]] = x.val;
if(x.u<A[0]){
q.push(node(A[x.u+1]+B[x.v],x.u+1,x.v));
}
}
for(int i=0; i<=tmp[0]; i++) A[i]=tmp[i];
}
stack <int> st;
int tarjan(int u, int fa){
int lowu=dfn[u]=++dfsclk;
for(int i=head[u]; ~i; i=E[i].next){
int v=E[i].v;
if(!dfn[v]){
st.push(i);
int lowv = tarjan(v, u);
lowu = min(lowu, lowv);
if(lowv>=dfn[u]){
arr[0]=0;
while(1)
{
int id=st.top(); st.pop();
arr[++arr[0]]=E[id].w;
if(id == i) break;
}
if(arr[0]>1) merge(ans, arr);
}
}
else if(dfn[v]<dfn[u]&&v!=fa){
st.push(i);
lowu=min(lowu,dfn[v]);
}
}
return lowu;
}
void find_bcc(int n)
{
for(int i=1; i<=n; i++) if(!dfn[i]) tarjan(i,-1);
}
int main()
{
int ks=0;
while(~scanf("%d %d", &n,&m))
{
init();
int sum=0;
for(int i=1; i<=m; i++){
int u,v,w;
scanf("%d %d %d", &u,&v,&w);
add(u,v,w);
add(v,u,w);
sum+=w;
}
scanf("%d",&k);
find_bcc(n);
unsigned res=0;
for(int i=1; i<=ans[0]; i++){
res += (unsigned)(sum-ans[i])*i;
}
printf("Case #%d: %u\n", ++ks, res);
}
return 0;
}