第六届河南省程序设计大赛 C 最舒适的路线 -并查集

异形卵潜伏在某区域的一个神经网络中。其网络共有N个神经元(编号为1,2,3,…,N),这些神经元由M条通道连接着。两个神经元之间可能有多条通道。异形卵可以在这些通道上来回游动,但在神经网络中任一条通道的游动速度必须是一定的。当然异形卵不希望从一条通道游动到另一条通道速度变化太大,否则它会很不舒服。

现在异形卵聚居在神经元S点,想游动到神经元T点。它希望选择一条游动过程中通道最大速度与最小速度比尽可能小的路线,也就是所谓最舒适的路线。

输入描述:

第一行: K     表示有多少组测试数据。 接下来对每组测试数据:第1行:       N  M第2~M+1行: Xi  Yi  Vi   (i=1,…..,M)表示神经元Xi 到神经元Yi之间通道的速度必须是Vi最后一行:     S  T     ( S  T )【约束条件】 2≤K≤5   1<N≤500   0<M≤5000   1≤ Xi, Yi , S , T ≤N   0< Vi <30000,Vi是整数。数据之间有一个空格。

输出描述:

对于每组测试数据,输出一行:如果神经元S到神经元T没有路线,输出“IMPOSSIBLE”。否则输出一个数,表示最小的速度比。如果需要,输出一个既约分数。

样例输入:

复制
2
3 2
1 2 2
2 3 4
1 3
3 3
1 2 10
1 2 5
2 3 8
1 3

样例输出:

2
5/4

下午做个题时候,没想到用并查集的思想,用dfs搜索每一条路,然后去判断,但是这个题死死的卡内存,题目64MB,我用了66MB,唉,dfs想了剪枝和优化,但是数据卡我内存,WA了好几发,后来看了网上的题解用并查集,然后死在了排序上,从大到小排!!!!!我从小到大排的,然后过了样例,WA了。先贴我自己写的dfs代码,如果不卡内存,我感觉应该能过,虽然我还没有跑对数器。

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long int ll;
const int maxn=50100;
int t,n,m,p,q;

struct node
{
	int to;
	int w;
	int next;
		
}edge[maxn];
int _min1;
int _max1;
bool vis[maxn];
int tot=0,cnt=0,ans;
int head[maxn];
double _min,_max;
double fs,in=inf;
void addedge(int u,int v,int l)
{
	edge[tot].to=v;
	edge[tot].w=l;
	edge[tot].next=head[u];
	head[u]=tot++;
}
int GCD(int x, int y)
{
	if(!x || !y)
	{
		return x > y?x:y;
	}
	for(int t;t=x%y,t;x=y,y=t);
	return y;
}
int dfs(int u)
{
	int v,w;
	for(int i=head[u];i!=-1;i=edge[i].next)
	{
		v=edge[i].to;
		w=edge[i].w;
		if(w<_min)
		{
			_min=w;
		}
		if(w>_max)
		{
			_max=w;
		}
		if(v==q)
		{
			fs=(_max/_min);
			if(fs==(int)fs&&fs==1)
			{
				printf("%d\n",(int)fs);
				return 0;
			}
			double x=fabs(fs-1);
			double y=fabs(in-1);
			if(x<y)
			{
				_min1=_min;
				_max1=_max;
				in=fs;	
			} 
			_max=0;
			_min=inf; 
		}
		else
		{
			dfs(v);
		}
	} 
}

int main()
{
#ifdef LOCAL
	freopen("D:/input.txt", "r", stdin);
#endif
	scanf("%d",&t);
	while(t--)
	{
		_min=inf;
		_max=0;
		memset(head,-1,sizeof(head));
		scanf("%d%d",&n,&m);
		for(int i=0;i<m;i++)
		{
			int u,v,l;
			scanf("%d%d%d",&u,&v,&l);
			addedge(u,v,l);	
		}
		scanf("%d%d",&p,&q);
		dfs(p);
		if(in==(int)in)
		{
			printf("%d\n",(int)in);
		}
		else
		{
//			printf("%d/%d\n",e[ans]._max,e[ans]._min);
			int num=GCD(_max1,_min1);
			printf("%d/%d\n",_max1/num,_min1/num);
		}
	}
	return 0;
}

然后是并查集代码

#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
#define inf 0x3f3f3f3f
#define mod 1000000007
const int maxn=5005;
struct node
{
	int x;
	int y;
	int v;
}edge[maxn];
int f[maxn];
bool cmp(node a, node b)
{
	return a.v>b.v;
}
int find(int x)
{
	if(x!=f[x])
	{
		return find(f[x]);
	}
	else
	{
		return x;
	}
}
void merage(int x,int y)
{
	x=find(x);
	y=find(y);
	if(x>y)
	{
		f[x]=y;
	}
	else
	{
		f[y]=x; 
	} 
}
int gcd(int a,int b)
{
	while(b!=0)
	{
		int t=a%b;
		a=b;
		b=t;
	}
	return a;
}
int main()
{
#ifdef LOCAL
	freopen("C:/input.txt", "r", stdin);
#endif
	
	int n, m,k,y;
	double l;
	scanf("%d",&k);
	while(k--)
	{
		int a,b;
		scanf("%d%d",&n,&m);
		for(int i=0;i<m;i++)
		{
			scanf("%d%d%d",&edge[i].x,&edge[i].y,&edge[i].v);
		}
		int s,t;
		scanf("%d%d",&s,&t);
		sort(edge,edge+m,cmp);
		l=inf*1.0;
		for(int i=0;i<m;i++)
		{
			for(int j=0;j<n;j++)
			{
				f[j]=j;
			}
			for(y=i;y<m;++y)
			{
				if(find(edge[y].x)!=find(edge[y].y))
				{
					merage(edge[y].x,edge[y].y);
				}
				if(find(s)==find(t))
				{
					break;	
				} 
			}
			if(y==m)
			{
				break;
			}
			if(edge[i].v*1.0/edge[y].v<l)
			{
				a=edge[i].v;
				b=edge[y].v;
				l=edge[i].v*(1.0)/edge[y].v;
			}
		}
		if(l==inf)
		{
			printf("IMPOSSIBLE\n");
		}
		else
		{
			if(a%b==0)
			{
				printf("%d\n",a/b);
			}
			else
			{
				printf("%d/%d\n",a/gcd(a,b),b/gcd(a,b));
			}
		}
	}	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/evildoer_llc/article/details/80331331