BZOJ-2654 tree

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xu0_zy/article/details/79980585

2654: tree
题目链接
时间限制: 30 Sec 内存限制: 512 MB
提交: 2782 解决: 1138
题目描述
给你一个无向带权连通图,每条边是黑色或白色。让你求一棵最小权的恰好有need条白色边的生成树。
题目保证有解。
输入
第一行V,E,need分别表示点数,边数和需要的白色边数。
接下来E行,每行s,t,c,col表示这边的端点(点从0开始标号),边权,颜色(0白色1黑色)。
输出
一行表示所求生成树的边权和。
V<=50000,E<=100000,所有数据边权为[1,100]中的正整数。
样例输入
2 2 1

0 1 1 1

0 1 2 0
样例输出
2
提示
原数据出错,现已更新 by liutian,但未重测—2016.6.24

题解
这道题目的想法很棒。

如果白色边边权会变,那么随着这个值的变大,所选白边条数变少。

我们要做的就是控制白边的数量,使得它正好等于need。

由于变化是单调的,所以,我们想到用二分枚举。

如果发现选的白边数≥need,那么L=mid+1。否则R=mid-1。

但是真正把代码写下了,却发现有一种特别的数据过不去:

当前的mid,使得白边数<need,但是mid+1使得白边数>need。

后来看过网上大神的博客才恍然大悟。

完全不用担心,因为题目保证有解,所以肯定是由于顺序的缘故。

也就是说肯定有一些和白边长度相等的黑边,我们可以把多余的白边替换掉。

若没有可替换的黑边,那么mid再大一些是完全可以的。

所以白边数≥need时就把当前的总代价赋给ans。

别忘了,有若干条白边的代价改变了,记得扣回来!

代码

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=5e4+5,maxm=1e5+5;
int n,m,ned,fa[maxn],n1,n2,ans;
struct js{
    int x,y,s;
}blk[maxm],wit[maxm];
int read()
{
    int ret=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=getchar();
    return ret*f;
}
int get(int x){return (fa[x]==x)?x:fa[x]=get(fa[x]);}
bool cmp(js x,js y){return x.s<y.s;}
int check(int tem)
{
    for (int i=1;i<=n;i++) fa[i]=i;
    int L1=1,L2=1,cnt=0,tot=n-1;
    js nxt;int p=1,sum=0;
    for (int i=1;i<=m;i++)
    {
        if (wit[L2].s+tem<=blk[L1].s) nxt=wit[L2++],p=1;
        else nxt=blk[L1++],p=0;
        int x=get(nxt.x),y=get(nxt.y);
        if (x==y) continue;fa[x]=y;
        sum+=nxt.s+tem*p;cnt+=p;
        if (!(--tot)) break;
    }
    if (cnt>=ned) ans=sum-(LL)ned*tem;
    //最重要的就是-ned*tem,扣回多出代价
    return cnt;
}
int main()
{
    n=read(),m=read();ned=read();
    for (int i=1;i<=m;i++)
    {
        int x=read()+1,y=read()+1,s=read(),c=read();
        if (c) blk[++n1]=(js){x,y,s};
          else wit[++n2]=(js){x,y,s};
    }
    sort(blk+1,blk+n1+1,cmp);
    sort(wit+1,wit+n2+1,cmp);//分成两组,可以避免二分check时多次排序
    blk[++n1].s=1e9;wit[++n2].s=1e9;
    int L=-105,R=105;ans=1e9;
    while (L<=R)
    {
        int mid=(R-L>>1)+L;
        int ask=check(mid);
        if (ask>=ned) L=mid+1;
        else R=mid-1;
    }
    printf("%d",ans);
    return 0;
}
阅读更多

Tree Tree Tree

11-05

Web应用程序中用拖放的方式产生的treeview加上节点为什么在.aspx.cs中看不到代码?rn如何才能手写代码产生树即节点?rn如果先用拖入的方式生成了树和节点,还能用代码加节点吗?rnrnrnusing System;rnusing System.Collections;rnusing System.ComponentModel;rnusing System.Data;rnusing System.Drawing;rnusing System.Web;rnusing System.Web.SessionState;rnusing System.Web.UI;rnusing System.Web.UI.WebControls;rnusing System.Web.UI.HtmlControls;rnrnnamespace WebApp1rnrn /// rn /// WebForm3 的摘要说明。rn /// rn public class treetest : System.Web.UI.Pagern rn protected Microsoft.Web.UI.WebControls.TreeView TreeView1;//这里是拖放后自动生成的;rn protected System.Web.UI.WebControls.Label Label1;rn TreeNode root = new TreeNode();rn//我手工代码加根节点就不能编译rnD:\Inetpub\wwwroot\WebApp1\treetest.aspx.cs(21): 找不到类型或命名空间名称“TreeNode”(是否缺少 using 指令或程序集引用?)rnrnrn rn private void Page_Load(object sender, System.EventArgs e)rn rn rn rn rnrn #region Web Form Designer generated codern override protected void OnInit(EventArgs e)rn rn //rn // CODEGEN:该调用是 ASP.NET Web 窗体设计器所必需的。rn //rn InitializeComponent();rn base.OnInit(e);rn rn rn /// rn /// 设计器支持所需的方法 - 不要使用代码编辑器修改rn /// 此方法的内容。rn /// rn private void InitializeComponent()rn rn this.Load += new System.EventHandler(this.Page_Load);rnrn rn #endregionrn rnrn

没有更多推荐了,返回首页