06年的天是晴朗的
一年省选两天生成树签到。
n*m可以过。
先排序,使边权单调。
然后再枚举最小值和最大值。
比较一下就好了。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#define N 20000
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &x){
x=0;
int f=1;
char ch=nc();
while(ch<'0'||ch>'9'){
if(ch=='-')
f=-1;
ch=nc();
}
while(ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=nc();
}
x*=f;
}
struct Front_star{
int u,v,w;
}e[N*4];
int cnt=0;
void add(int u,int v,int w){
cnt++;
e[cnt].u=u;
e[cnt].v=v;
e[cnt].w=w;
}
bool cmp(Front_star a,Front_star b){
return a.w<b.w;
}
int fa[N]={0};
int n,m;
int s,t;
int getfa(int x){
if(fa[x]==x){
return x;
}
else{
return fa[x]=getfa(fa[x]);
}
}
void uni(int x,int y){
int dx=getfa(x);
int dy=getfa(y);
fa[dx]=dy;
}
int gcd(int x,int y){
while(y){
int temp=y;
y=x%y;
x=temp;
}
return x;
}
int main(){
read(n);
read(m);
for(int i=1;i<=m;i++){
int u,v,w;
read(u);
read(v);
read(w);
add(u,v,w);
}
read(s);
read(t);
sort(e+1,e+1+cnt,cmp);
int ans1=0,ans2=0;
e[0].w=0;
for(int i=1;i<=m;++i){
for(int j=1;j<=n;++j){
fa[j]=j;
}
fa[0]=2000;
int idx=20000;
e[idx].w=50000;
// cout<<i<<endl;
for(int j=i;j<=m;++j){
uni(e[j].u,e[j].v);
// cout<<j<<endl;
if(getfa(s)==getfa(t)){
idx=j;
break;
}
}
if(i==1&&getfa(s)!=getfa(t)){
cout<<"IMPOSSIBLE";
return 0;
}
if(e[ans2].w*e[i].w>=e[ans1].w*e[idx].w){
ans1=i;
ans2=idx;
// cout<<ans1<<" "<<ans2<<endl;
}
}
// cout<<ans1<<"---"<<ans2;
int G=(gcd(e[ans1].w,e[ans2].w));
ans1=e[ans1].w/G;
ans2=e[ans2].w/G;
if(ans1==1){
cout<<ans2;
}
else{
cout<<ans2<<"/"<<ans1;
}
}

本文介绍了一个06年的省级选拔赛中的生成树算法题解,通过排序边权并枚举最小值和最大值的方法求解,提供了一段完整的C++代码实现。
401

被折叠的 条评论
为什么被折叠?



