有一个
n
个点
记一个割
(S,T)
的slimness为跨在
S
和
找到一个slimness最小的割,输出slimness。
n≤14000,m≤30000
时限5s
dls太强辣
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<vector>
#define pb push_back
#include<bitset>
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){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
const int N=14005;
const int M=30005;
struct edge{
int u,v,w;
bool operator < (const edge&B) const{
return w>B.w;
}
}ed[M];
int n,m;
int size[N],fat[N],clk[N];
inline int Fat(int u){
return u==fat[u]?u:fat[u]=Fat(fat[u]);
}
struct event{
int l,r,w;
event(int l=0,int r=0,int w=0):l(l),r(r),w(w) { }
};
double Ans=1e30;
bitset<N> B;
inline void Solve(int l,int r,vector<event> &vec){
bitset<N> tmp; tmp=B;
if (l==r){
for (int i=0;i<(int)vec.size();i++)
if (vec[i].l<=l && r<=vec[i].r)
B|=B<<vec[i].w;
for (int i=1;i<=n/2;i++)
if (B[i])
Ans=min(Ans,(double)ed[l+1].w/i);
B=tmp;
return;
}
vector<event> v1,v2;
int mid=(l+r)>>1;
for (int i=0;i<(int)vec.size();i++)
if (vec[i].l<=l && r<=vec[i].r)
B|=B<<vec[i].w;
else{
if (vec[i].l<=mid) v1.pb(vec[i]);
if (vec[i].r>mid) v2.pb(vec[i]);
}
Solve(l,mid,v1);
Solve(mid+1,r,v2);
B=tmp;
}
int main(){
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(n); read(m);
for (int i=1;i<=m;i++)
read(ed[i].u),read(ed[i].v),read(ed[i].w),ed[i].u++,ed[i].v++;
sort(ed+1,ed+m+1);
for (int i=1;i<=n;i++) fat[i]=i,size[i]=1,clk[i]=0;
vector<event> vec;
for (int i=1;i<=m;i++){
int x=Fat(ed[i].u),y=Fat(ed[i].v);
if (x==y) continue;
vec.pb(event(clk[x],i-1,size[x]));
vec.pb(event(clk[y],i-1,size[y]));
fat[x]=y; size[y]+=size[x]; clk[y]=i;
}
for (int i=1;i<=n;i++) if (fat[i]==i) vec.pb(event(clk[i],m,size[i]));
B[0]=1;
Solve(0,m,vec);
printf("%.11lf\n",Ans);
return 0;
}