ACdream 1135(MST-最小生成树边上2个值,维护第一个最小的前提下让另一个最小)

F - MST

Time Limit:  2000/1000MS (Java/Others)  Memory Limit:  128000/64000KB (Java/Others)
Submit Status

Problem Description

Given a connected, undirected graph, a spanning tree of that graph is a subgraph that is a tree and connects all the vertices together.  A single graph can have many different spanning trees. We can also assign a weight to each edge, which is a number representing how unfavorable it is, and use this to assign a weight to a spanning tree by computing the sum of the weights of the edges in that spanning tree. A minimum spanning tree (MST) is then a spanning tree with weight less than or equal to the weight of every other spanning tree.
------ From wikipedia
Now we make the problem more complex. We assign each edge two kinds of weight: length and cost. We call a spanning tree with sum of length less than or equal to others MST. And we want to find a MST who has minimal sum of cost.

Input

There are multiple test cases.
The first line contains two integers N and M indicating the number of vertices and edges in the gragh.
The next M lines, each line contains three integers a, b, l and c indicating there are an edge with l length and c cost between a and b.

1 <= N <= 10,000
1 <= M <= 100,000
1 <= a, b <= N
1 <= l, c <= 10,000

Output

For each test case output two integers indicating the sum of length and cost of corresponding MST.
If you can find the corresponding MST, please output "-1 -1".

Sample Input

4 5
1 2 1 1 
2 3 1 1
3 4 1 1
1 3 1 2
2 4 1 3

Sample Output

3 3

图中边有2个值l,c,求关于l的MST,在此基础上求min∑c


直接把边按l从小到大(第一关键字),c从小到大(第二关键字)排序,然后用Kruskal算法



#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<iostream>
#include<cmath>
#include<cctype>
#include<ctime>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Lson (x<<1)
#define Rson ((x<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (1000000007)
#define MAXN (1000+10)
long long mul(long long a,long long b){return (a*b)%F;}
long long add(long long a,long long b){return (a+b)%F;}
long long sub(long long a,long long b){return (a-b+(a-b)/F*F+F)%F;}
typedef long long ll;
int n;
char a[MAXN][MAXN];
ll p10[MAXN]={0};
ll pow2(ll b)  
{
   if (b==1) return 10;  
   if (b==0) return 1;  
   if (p10[b]) return p10[b];
   ll p=pow2(b/2)%F;  
   p=(p*p)%F;  
   if (b&1)  
   {  
       p=(p*10)%F;  
   }  
   p10[b]=p;
   return p;  
}  
ll pow2(ll a,ll b)
{
	if (b==1) return a;
	if (b==0) return 1;
	ll p=pow2(a,b/2)%F;
	p=p*p%F;
	if (b&1)
	{
		p=(p*a)%F;
	}
	return p;
}
ll tot[MAXN]={0};
ll mulinv(ll a)
{
	return pow2(a,F-2);
}
int main()
{
//	freopen("sum.in","r",stdin);
//	freopen("sum.out","w",stdout);
	scanf("%d",&n);
	For(i,n)
	{
		scanf("%s",a[i]+1);
		
	}
	/*
	For(i,n)
	{
		For(j,n) cout<<a[i][j];
		cout<<endl;
	}
	*/
	For(i,n)
	{
		For(j,n) tot[i]+=a[i][j]-'0'+a[j][i]-'0';		
	}
	
	
//	For(i,n) cout<<tot[i]<<endl;
	
//	cout<<mul(pow2(10,1232),mulinv(pow2(10,1232)))<<endl;
//	cout<<mulinv(9);

	ll c9=mulinv(9);
	
	For(i,n) p10[i]=pow2(i);
	
	
	ll ans=0;
	For(i,n)
	{
		ll t=sub(p10[n-i+1],1),a=tot[i];
		t=mul(t,c9);
		t=mul(a,t);
		ans=add(ans,mul(t,i));		
	}
	cout<<ans<<endl;
	
	
	return 0;
}



你可能感兴趣的:(ACdream 1135(MST-最小生成树边上2个值,维护第一个最小的前提下让另一个最小))