hdu 3371 Connect the Cities

Connect the Cities

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


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
此题说明一点 在杭电上提交 用c++好过 用G++可能会超时 因为G++输入很费时间 需要优化输入
这里给出两种算法 kruskul算法 (利用并查集)
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int set[510],sum,num,rank[510];
struct Tnode
{
    int v1,v2,cost;
} node[25005];
void init(int n)
{
    int i;
    for(i=1; i<=n; i++)
	{
		set[i]=i;
		rank[i]=1;
	}
    sum=0;
    num=n;
}
int find(int x)
{
	int r=x,n;
    while(set[r]!=r) r=set[r];
	while(x!=r)
	{
		n=set[x];
		set[x]=r;
		x=n;
	}
    return r;
}
void merge(int a,int b)
{
    int x,y;
    x=find(a);
    y=find(b);
    if(x!=y)
    {
		if(rank[x]<rank[y])  set[x]=y;
        else
		{
			set[y]=x;
			if(rank[x]==rank[y])  rank[x]++;
		}
        num--;
    }
}
bool cmp(const Tnode &a, const Tnode &b)
{
    return  a.cost<b.cost;
}
int  getint()       //读取整数函数  可以优化输入  节约时间
{
	char c;
	int t=0;
	c=getchar();
	while(c<'0'||c>'9')  c=getchar();
	while(c>='0'&&c<='9')
	{
		t=10*t+c-'0';
		c=getchar();
	}
	return t;
}		
int main()
{
    int n,i,x1,x2,m,k,a,b,cnt,t,j;
//   scanf("%d",&t);
	t=getint();
    while(t--)
    {
		n=getint();
		m=getint();
		k=getint();
        init(n);
        for(i=1; i<=m; i++)
        {
			node[i].v1=getint();
			node[i].v2=getint();
			node[i].cost=getint();
        }
        for(i=1; i<=k; i++)
        {
			cnt=getint();
			a=getint();
            for(j=1;j<cnt;j++)
            {
				b=getint();
                merge(a,b);
//				printf("a:%d b:%d num:%d\n",a,b,num);
            }
		}
            sort(node+1,node+m+1,cmp);
            for(i=1; num>1&&i<=m; i++)
            {
                x1=find(node[i].v1);
                x2=find(node[i].v2);
                if(x1!=x2)
                {
                    merge(node[i].v1,node[i].v2);
//					printf("v1:%d v2:%d num:%d  i:%d\n",node[i].v1,node[i].v2,num,i);
                    sum+=node[i].cost;
                }
            }
        if(num==1)  printf("%d\n",sum);
		else printf("-1\n");
    }
    return 0;
}

prime 算法 (适用于点少边多的情况)

    
    
    
    

    
    
    
    
#include<stdio.h>
#include<math.h>
#include<string.h>
#define INF 50000005
int dist[505],vis[505],city[505][505],n,m,sum;
void init(int n)
{
	int i,j;
	sum=0;
	for(i=1;i<=n;i++)
		dist[i]=INF;	
	for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
			city[i][j]=INF;
	memset(vis,0,sizeof(vis));
}
void disjk()
{
	int i,j,min,k,now=1;
	vis[1]=1;
	for(i=1;i<n;i++)
	{
		for(j=1;j<=n;j++)
		{
			if(vis[j]==0&&city[now][j]<dist[j]&&j!=now)
				dist[j]=city[now][j];
		}		
		min=INF+5;
		k=0;
		for(j=1;j<=n;j++)
		{
			if(vis[j]==0&&dist[j]<min) 
			{
				min=dist[j];
				k=j;
			}
		}
		sum+=dist[k];
		now=k;
		vis[k]=1;
//		printf("now:%d,dis:%d\n",now,dist[now]);
	}
}
int main()
{
	int i,t,j,jj,le,ri,d,k,cnt,a[105],b;
	scanf("%d",&t);
	while(t--)
	{
	    scanf("%d%d%d",&n,&m,&k);
		init(n);
		for(i=1;i<=m;i++)
		{
			scanf("%d%d%d",&le,&ri,&d);
			if(d<city[le][ri])  city[le][ri]=city[ri][le]=d;    //注意 if 的判断  这是此题坑的一个位置 
                                                                            //测试数据中有 两个点给出多条距离不同的路的情况  WA了很多次
		}
		for(i=1; i<=k; i++)
        {
            scanf("%d",&cnt);           
            for(j=1;j<=cnt;j++)
                scanf("%d",&a[j]);
			for(j=1;j<cnt;j++)
				for(jj=j+1;jj<=cnt;jj++)
			        city[a[j]][a[jj]]=city[a[jj]][a[j]]=0;          
		}
		disjk();
		if(sum<INF)  printf("%d\n",sum);
		else   printf("-1\n");
	}	  
	return 0;
}





 
 
 
 
 
 

你可能感兴趣的:(hdu 3371 Connect the Cities)