A - Tea-drinking-Gym 100703A-优先队列/最小生成树


 http://codeforces.com/gym/100703/problem/A

题意是n行字符串,长度m

先按题目求出每行之间的“距离”


然后要求 把所有字符串连起来,   输出生成数 中 两个字符串距离的最大值

法1

此题可以 先对for两遍 o(n^2) n=1000求出所有边

然后按边权升序排序,  然后 每天添加一条边就用并查集把两个点合并,

如果取出的边 的两点根节点想同,就丢掉,否则选取 最后得到的也是最优的

//

法2

当时我是用优先队列做的 ,先得到一条距离最小的边

vis标记掉两个点

然后把 所有与这两个顶点 连的所有边 都丢到优先队列里

然后取出最顶端的,即最小的边,如果不满足 ( 一端点被选过,另一端点没被选过)  就丢掉,如果满足就选取该边

并把该没选过的点用vis标记为选过,

然后把 所有与这一个顶点 连的所有边 都丢到优先队列里

不断重复  也是最优的  不过麻烦了点


#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<string>
#include<string.h>
#include<stack>
#include<queue>
#define MAX 1000005
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
struct node
{
	int dist;
	int x;
	bool operator < (const node&  b) const
	{
		return dist>b.dist;
	}
};
 int ans[1005][1005];
char tm[1005][35];
int n,m;
int ok=0;
int min_point_x=0;
int min_point_y=0;
int mark=900;
int cal(int x1,int x2)
{
	int i;
	int maxx=0;
	for (i=1;i<=m;i++)
	{
		if (abs(tm[x1][i]-tm[x2][i])>maxx)
			maxx=abs(tm[x1][i]-tm[x2][i]);
	}
		 
			ans[x1][x2]=maxx;

		if (maxx<mark)
		{
			mark=maxx;
			 min_point_x=x1;
			 min_point_y=x2;
		}
	//  cout<<x1<<"---"<<x2<<"---dist:"<<maxx<<endl; 
		return 0;
}
int cmp(node a,node b)
{
	return a.dist<b.dist;
}
int vis[1005];

priority_queue <node> qq;
int main()
{
	int i,j;
    scanf("%d%d",&n,&m);
	getchar();

	for (i=1;i<=n;i++)
	{
		scanf("%s",tm[i]+1); 
	}
 	for (i=1;i<=n;i++)
	{
		for (j=1;j<=n;j++)
		{
			if (j==i) continue;
			cal(i,j);
		} 
	} 
 

	int maxxxx=0;   
	node tmp;
	tmp.x= min_point_x;

	vis[tmp.x] =1;
node ttt;
	for (i=1;i<=n;i++)
	{
		if (ans[tmp.x][i]==0||vis[i]==1) continue; 
		ttt.x=i;
		ttt.dist=ans[tmp.x][i];
		qq.push(ttt);
	}
		    	tmp.x= min_point_y;
					vis[tmp.x] =1;
		for (i=1;i<=n;i++)
	{
		if (ans[tmp.x][i]==0||vis[i]==1) continue; 
		ttt.x=i;
		ttt.dist=ans[tmp.x][i];
		qq.push(ttt);
	}
  node tm;
while(!qq.empty())
{
	 tm=qq.top();
	 qq.pop();
		if (vis[tm.x]==1) continue;
		vis[tm.x]=1;
		
	 if (tm.dist>mark)
		 mark=tm.dist;
		for (i=1;i<=n;i++)
	{
		if (ans[tm.x][i]==0||vis[i]==1) continue; 
		ttt.x=i;
		ttt.dist=ans[tm.x][i];
		qq.push(ttt);
	}

}


	
	printf("%d\n",mark);
				
				return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值