HDU3371 Connect the Cities(prim)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_42391248/article/details/82143640

Connect the Cities

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 24887    Accepted Submission(s): 5746

Problem Description

In 2100, since the sea level rise, most of the cities disappear. Though some survived cities are still connected with others, but most of them become disconnected. The government wants to build some roads to connect all of these cities again, but they don’t want to take too much money. 

Input

The first line contains the number of test cases.
Each test case starts with three integers: n, m and k. n (3 <= n <=500) stands for the number of survived cities, m (0 <= m <= 25000) stands for the number of roads you can choose to connect the cities and k (0 <= k <= 100) stands for the number of still connected cities.
To make it easy, the cities are signed from 1 to n.
Then follow m lines, each contains three integers p, q and c (0 <= c <= 1000), means it takes c to connect p and q.
Then follow k lines, each line starts with an integer t (2 <= t <= n) stands for the number of this connected cities. Then t integers follow stands for the id of these cities.

Output

For each case, output the least money you need to take, if it’s impossible, just output -1.

Sample Input

1
6 4 3
1 4 2
2 6 1
2 3 5
3 4 33
2 1 2
2 1 3
3 4 5 6

Sample Output

1

题意:给出n,m,k.表示n个城市,接下来m行每行有三个数a,b,c表示从a到b修路需要花费c,接下来k行,每行第一个数表示有d个城市相连,后面跟g个城市的编号。求把所以的城市都连起来需要的最小花费。

题解:正常的prim算法就能解决,但是本题点比较多,所以用prim算法用时会高一点。需要注意的是本题的从a到b的路可能有多条,所以建图的时候需要把最小的权值记进去。

具体代码如下:

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int map[510][510];
int d[510];
int visit[510];
const int INF=1<<30;
int main()
{
	int N;
	cin>>N;
	while(N--)
	{
		int i,j,m,n,k;
		scanf("%d%d%d",&n,&m,&k);
		memset(visit,1,sizeof(visit));
		memset(d,0,sizeof(d));
		for(i=0;i<=n;i++)
            for(j=0;j<=n;j++)
                map[i][j]=map[j][i]=(i==j?0:INF);
		for(i=0;i<m;i++)
		{
			int a,b,c;
			scanf("%d%d%d",&a,&b,&c);
			if(map[a][b]>c)//保证权值最小,不然会WA的 
				map[a][b]=map[b][a]=c;
		}	
		for(i=0;i<k;i++)
		{
			int nn;
			scanf("%d",&nn);
			int a[1000];
			for(j=0;j<nn;j++)
				scanf("%d",&a[j]);
			for(j=0;j<nn-1;j++)
				for(int jj=j+1;jj<nn;jj++)
					map[a[j]][a[jj]]=map[a[jj]][a[j]]=0;		
		}
		//prim							
		for(i=1;i<=n;i++)
			d[i]=map[i][1];
		int sum=0;
		visit[1]=0;
		for(i=1;i<=n;i++)
		{
			int minn=INF;
			int temp;
			for(j=1;j<=n;j++)
				if(visit[j]&&d[j]<minn)
				{
					minn=d[j];
					temp=j;
				}
			if(minn==INF)
				break;
			sum+=minn;
			visit[temp]=0;
			for(j=1;j<=n;j++)
				if(visit[j]&&d[j]>map[j][temp])
					d[j]=map[j][temp];			
		}
		int flag=0;
		for(i=1;i<=n;i++)
			if(d[i]==INF)
			{
				flag=1;
				break;
			}
		if(flag)
			cout<<"-1"<<endl;
		else
			cout<<sum<<endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_42391248/article/details/82143640