1458: 征兵
时间限制: 1 Sec 内存限制: 128 MB提交: 98 解决: 49
[提交][状态][讨论版]
题目描述
一个国王,他拥有一个国家。最近他因为国库里钱太多了,闲着蛋疼要征集一只部队要保卫国家。他选定了N个女兵(编号0...N-1)和M个男兵(编号0...M-1),但事实上每征集一个兵他就要花10000RMB,即使国库里钱再多也伤不起啊。他发现,某男兵和某女兵之间有某种关系(往正常方面想,一共R种关系),这种关系可以使KING少花一些钱就可以征集到兵,不过国王也知道,在征兵的时候,每一个兵只能使用一种关系来少花钱。这时国王向你求助,问他最少要花多少的钱。
输入
第一行:T,一共T组数据。
接下来T组数据,
第一行包括N,M,R
接下来的R行包括Xi,Yi,Vi
表示如果招了第Xi个女兵,再招第Yi个男兵能省Vi元(同样表示如果招了第Yi个男兵,再招第Xi个女兵能也省Vi元)
输出
共T行,表示每组数据的最终花费是多少(因为国库里的钱只有2^31-1,所以保证最终花费在maxlongint范围内)
样例输入
2
5 5 8
4 3 6831
1 3 4583
0 0 6592
0 1 3063
3 3 4975
1 3 2049
4 2 2104
2 2 781
5 5 10
2 4 9820
3 2 6236
3 1 8864
2 4 8326
2 0 5156
2 0 1463
4 1 2439
0 4 4373
3 4 8889
2 4 3133
样例输出
71071
54223
提示
数据范围
数据保证T<=5
,m,n<=10000,r<=50000,Xi<=m,Yi<=n,Vi<=10000,结果<=2^31-1
题解:这题实际上是一个最大生成树,用总花费减去最多节省的钱数即为答案。
代码如下:
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 using namespace std; 6 struct edge{ 7 int x,y,val; 8 }e[50005]; 9 int fa[50005],n,m,r,t; 10 bool cmp(edge a,edge b){ 11 return a.val>b.val; 12 } 13 int find(int x){ 14 if(fa[x]==x) return x; 15 return fa[x]=find(fa[x]); 16 } 17 void unite(int x,int y){ 18 int fx=find(x),fy=find(y); 19 if(fx==fy) return; 20 fa[fx]=fy; 21 } 22 int kruskal() 23 { 24 sort(e,e+r,cmp); 25 for(int i=0;i<n+m;i++) fa[i]=i; 26 int ans=0; 27 for(int i=0;i<r;i++){ 28 edge ed=e[i]; 29 if(find(ed.x)!=find(ed.y)){ 30 unite(ed.x,ed.y); 31 ans+=ed.val; 32 } 33 } 34 return ans; 35 } 36 int main() 37 { 38 scanf("%d",&t); 39 while(t--){ 40 scanf("%d%d%d",&n,&m,&r); 41 for(int i=0;i<r;i++){ 42 scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].val); 43 e[i].y+=n; 44 } 45 printf("%d ",10000*(n+m)-kruskal()); 46 } 47 return 0; 48 }