Problem A: 古老的羊皮卷
Time Limit: 3 Sec Memory Limit: 128 MB
Description
奇奇,一个响亮的名字在ACM界.如今奇奇已经腰缠万贯,飞黄腾达,日子过的是无比的滋润.是什么使他到了如此的地位?如果你要这么问,奇奇会不假思索的告诉你:"ACM! 是ACM让他思维敏捷而缜密,是ACM让他头脑灵活而聪慧,是ACM让他谋事果断而细心......".但每天安逸的生活使得奇奇很是烦闷,由于他小时候梦想着找宝藏,于是奇奇打算去历(zuo)险(si).这不,瞎猫碰上死耗子,还真让他不知从哪得来了一张古老的羊皮书.找个安静隐秘的地方,奇奇打开羊皮卷,内容甚是复杂,不过幸亏奇奇学过ACM,利用早年所学的的图论、计算几何、数论加密等一系列方法终于把羊皮卷还原了,原来是一张古代藏宝图.只见地图上有 n 个可能藏有宝物的地方,这 n 个地方一共有 m 条路, 每条路的两端连通着两个地方,路两两互不相通,每两个地方之间仅存在一条路,路是双向可达的.每条路都有一个凶险值,奇奇不知道具体的凶险值是多少,只知道路越长则凶险值越小,每条路的长度在藏宝图中都有标明.奇奇想去一一探查这 n 个地方,为了使得总的凶险值越小,他想选择尽量少的路能到达这 n 个地方,其次在路尽量少的情况下保证总的凶险值也尽量少,也即他所选择的各个路的距离之和最大.这是一个复杂的问题,奇奇已经力不从心了,于是只好求学弟学妹们帮他找到一个方案满足他的要求,如果你找到了,那么他将会把他所得的藏宝分你一半,否则你就会被陷入绝望的奇奇"嘿嘿嘿".
Input
输入数据有多组,对于每组数据包含若干行.每组数据的第一行有两个数字 n 和 m (0 < n <= 1000, 0 <= m < 1000,000),代表着有 n 个奇奇要去的地方(分别编号为1, 2, ..., n), 这 n 个地方存在 m 条路.紧接着 m 行,每行有三个数 i, j, k, 代表着第 i 号藏宝地到第 j 号藏宝地之间的路的距离为 k (0 < u, v <= n. 0 < w < 100,000), 输入数据保证 n 个地方相互连通.
Output
对于每组输入,在单独的一行输出一个数字,代表着满足奇奇要求的路线中每条路的距离之和.
Sample Input
4 5
1 2 9
4 2 7
3 1 6
3 2 3
4 3 5
Sample Output
22
HINT
奇奇要去 4 个地方, 这 4 个地方由 5 条路连通, 选择 1 --> 2, 1 --> 3, 2 --> 4 这三条路将使得总路线最长为 22.
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define INF 99999999
int n,m;
int mp[1008][1008];
int used[1008],low[1000008];
int prime(int n)
{
int sum=0,i,time=1,k;
memset(used,0,sizeof(used));//清零
used[1]=1;//选取第一个点
for(i=2;i<=n;i++)
{
low[i]=mp[1][i];//与第一个点相连的线段的权值存在数组中
//printf("%d\n",low[i]);
}
while(time<=n-1)//因为每循环一次找出一个点,所以只要循环n-1次一定能够把最小生成树找出来
{
int it=-1;//先将最小值设成一个大数
int j=0;
for(k=2;k<=n;k++)
{
//printf("low[k]=%d\n",low[k]);
if(low[k]>it&&used[k]==0)//找两个点之间的最短距离且另一个点没用过
{
it=low[k];//更新最小值
j=k;
}
}
//printf("it=%d\n",it);
sum=sum+it;//加上最小值
used[j]=1;//这个点用过标记为1
//printf("j=%d\n",j);
for(k=2;k<=n;k++)
{
if(mp[j][k]>low[k]&&used[k]==0)//找这个点与其他点之间的最短距离且另一个点也没用过
{
low[k]=mp[j][k];//更新最小值
//printf("low[k]=%d\n",low[k]);
}
}
time++;
}
return sum;
}
int main()
{
while(cin>>n>>m)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
mp[i][j]=-99999;
}
}
for(int i=1;i<=m;i++)
{
int x,y,val;
cin>>x>>y>>val;
mp[x][y]=val;
mp[y][x]=val;
}
/*for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
printf("%d ",mp[i][j]);
}
printf("\n");
}*/
cout<<prime(n)<<endl;
}
return 0;
}
注意:备注差不多是反着的 由之前最小生成树的模板改的 。。。这个是不容易超时的。。。