【HAOI2006】旅行(并查集暴力)

传送门

Solution:

并查集暴力搞。

挺像kruskal找最小生成树的,按边权从小到大排序,枚举最小边,然后不停的加比这条边大的边,直到s,t连通。

#include<bits/stdc++.h>
#define N 505
#define M 5005
using namespace std;
int n,m,s,t,father[N];
struct node
{
	int from,to,val;
}edge[2*M];

inline bool cmp(const node &a,const node &b)
{
	return a.val<b.val;
}
inline int getfather(int x)
{
	if(father[x]==x)	return x;
	return father[x]=getfather(father[x]);
}
inline int gcd(int x,int y)
{
	if(y>x)	return gcd(y,x);
	if(!y)	return x;
	return gcd(y,x%y);
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(NULL),cout.tie(NULL);
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	{
		int x,y,z;
		cin>>x>>y>>z;
		edge[i].to=y;
		edge[i].from=x;
		edge[i].val=z;
	}
	cin>>s>>t;
	sort(edge+1,edge+m+1,cmp);
	int ans_max,ans_min;
	for(int i=1;i<=m;i++)
	{
		int j;
		for(j=1;j<=n;j++)	father[j]=j;
		for(j=i;j<=m;j++)
		{
			int ax=getfather(edge[j].from);
			int bx=getfather(edge[j].to);
			if(ax!=bx)
			{
				father[ax]=bx;
				if(getfather(s)==getfather(t))	break;
			}
		}
		if(i==1&&getfather(s)!=getfather(t))
		{
			cout<<"IMPOSSIBLE"<<endl;
			return 0;
		}
		if(getfather(s)!=getfather(t))	break;	//小小的剪枝 
		if(ans_max*edge[i].val>=ans_min*edge[j].val){//只是移一下项 
			ans_max=edge[j].val;
			ans_min=edge[i].val;
		}
	}
	int a=gcd(ans_max,ans_min);
	if(a==ans_min)	cout<<ans_max/ans_min<<endl;
	else cout<<ans_max/a<<"/"<<ans_min/a<<endl;
	return 0;
}
posted @ 2018-08-08 22:59  Patrickpwq  阅读(91)  评论(0)    收藏  举报