[51nod1640] 天气晴朗的魔法

来源:互联网 发布:软件外包公司销售 编辑:程序博客网 时间:2024/05/01 12:24

题目链接

题解:题目描述非常excited。显然,二分可以搞(因为没开long long和没写读优又T又WA了n次),最后用读优卡过去了。不过,只需要先kruskal一次求最小生成树(条件1,最大边权尽量小),记录生成最大边权MX,再以MX为最大边权跑最大生成树就行了(条件2,权值和尽量大),比二分不知道高到那里去了

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <climits>using namespace std;const int M=100005;#define INF LLONG_MAX/100000#define ll long longint t=1,n,m;ll l,r,mid,ans,sum;struct edge{    int u,v,val;}e[M*3];int f[M];ll read(){    char c=getchar();ll x=0,f=1;    while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}    while(c>='0'&&c<='9') x=(x*10)+c-48,c=getchar();    return x*f;}int fd(int x){    return f[x]==x?x:f[x]=fd(f[x]);}bool cmp(edge a,edge b){    return a.val>b.val;}bool ok(ll x){    int tot=0;sum=0;    for(int i=1;i<=n;i++) f[i]=i;    for(int i=1;i<=m;i++)    {        if(e[i].val>x) continue;        int x=fd(e[i].u),y=fd(e[i].v);        if(x!=y){            f[x]=y;tot++;            sum+=e[i].val;        }    }    return tot==n-1;}void init(){    cin>>n>>m;    for(int i=1;i<=m;i++)    e[i].u=read(),e[i].v=read(),e[i].val=read();    sort(e+1,e+1+m,cmp);}void work(){    l=0,r=INF;    while(l<=r)    {        mid=(l+r)>>1;        if(ok(mid))        ans=sum,r=mid-1;        else l=mid+1;    }    printf("%lld\n",ans);}int main(){    init();    work();    return 0;}
0 0