B. 小妹妹送很多快递 2014新生暑假个人排位赛09
题目描述
Mays王国的女王大人每天过着自由自在的生活,她最大的乐趣就是给邻国的帅气王子写信。但是最近,Mays王国的叔叔们变得很无聊,他们知道女王大人每次都把信委托给皇家小妹妹快递公司的小妹妹们,于是叔叔们给每一条路都设立了路障,只有小妹妹们给他们表演节目才会让小妹妹们过去。
在每一个路障,都有不同数量的叔叔,只有表演的小妹妹的数量不少与叔叔的数量的时候叔叔才会放她们过去。
可是七夕快要到了,Masy王国的每一个人都在给自己的情人写信。
Mays王国由n个地区组成,一些双向的道路连接着这些地区。注意两个地区之间可能有多条道路相通。
无聊的单身的beegerous已经算出了从一点到另一点送信最少需要的小妹妹的数量,为了表达对世界的不满,他脑补出了小妹妹们给任意两个点之间送信的画面,这样她们一共需要送n*(n-1)次信!如果所有的信件必须同一时间发出,这样每一次快递都需要由不同的小妹妹们来送!这样就会有好多好多小妹妹在Mays王国的道路上忙碌了。
请问,按上述脑补情形,皇家小妹妹快递公司一共需要派出多少小妹妹。
输入格式
输入第一行为数据组数T(T<=10),接下来T组数据,每组第一行为n,m,,2<=n<=10000,1<=m<=100000,表示Mays王国的道路由n个节点组成,接下来m行,每行一组u,v,c表示连接节点u,v的一条无向道路,且路障上有c个叔叔,1<=u,v<=n,0<=c<=100。
输入保证任意两点之间可达。
输出格式
每组数据输出一个数字,表示小妹妹快递公司最少需要派出的小妹妹数量。
输入样例
1
3 3
1 2 1
2 3 1
1 3 3
输出样例
6
hint:
9种送快递的方式及花费为:
1 --> 2: 1
1 --> 3: 1
2 --> 1: 1
2 --> 3: 1
3 --> 1: 1
3 --> 2: 1
答案为6
思路:由于这一次要求每一个的最少的小妹妹数。由于小妹妹数是不会消耗的。我们可以从边开始拓展。先排序。然后从小到大加入边后并查集,所需的小妹妹即两个集合的小妹妹的个数相乘乘以新加进来的v再乘以2(由于需要互相送)。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
//#define LOCAL
using namespace std;
struct Edge
{
int from,to,v,next;
bool operator < (const Edge &a) const
{
return v<a.v;
}
}e[200005];
int father[20005],sum[20005],cnt;
int n,m;
int h[20005];
long long ans;
void AddEdge(int x,int y,int v)
{
cnt++;e[cnt].from=x;e[cnt].to=y;e[cnt].v=v;e[cnt].next=h[x];h[x]=cnt;
}
int getfather(int x)
{
if(x==father[x])return x;
father[x]=getfather(father[x]);
return father[x];
}
void Union(int x,int y,int v)
{
int fx=getfather(x),fy=getfather(y);
if(fx!=fy)
{
father[fy]=fx;
ans=ans+((long long)sum[fx]*(long long)v*(long long)2*(long long)sum[fy]);
sum[fx]=sum[fx]+sum[fy];
}
}
int main()
{
#ifdef LOCAL
freopen("input.txt","r",stdin);
#endif // LOCAL
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
cnt=0;
memset(h,-1,sizeof(h));
int x,y,v;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&v);
if(v==0)v=1;
AddEdge(x,y,v);
AddEdge(y,x,v);
}
sort(e+1,e+1+cnt);
for(int i=1;i<=n;i++)father[i]=i;
for(int i=1;i<=n;i++)sum[i]=1;
ans=0;
for(int i=1;i<=cnt;i++)
{
x=e[i].from;y=e[i].to;v=e[i].v;
Union(x,y,v);
}
printf("%lld\n",ans);
}
return 0;
}