BZOJ 2095 [Poi2010]Bridges 二分+最大流

本文介绍了一个结合欧拉回路与二分搜索算法的问题解决思路。具体地,文章探讨了如何在一个带权双向图中寻找一个从特定起点出发的欧拉回路,使该回路上最大边权值最小。通过使用二分搜索确定最大权值的范围,并借助最大流算法验证欧拉回路的存在性。

题意:
给定一张图,每条边双向且双向都有权值,求一个从1开始的欧拉回路,使得回路上的边的最大权值最小。
解析:
最大值最小!!
二分!!二分!!
第一部分完成辣,二分出路上的最大权值。
然后这时候我们要处理下所有的边,如果边上权值大于我们二分的值的话显然是不可取的。
这其实就是个混合图的欧拉回路问题。
首先无向的边我们任意记录一下出度入度,然后有向边直接记录出度入度。
如果有一个点的出度入度之差是奇数那么显然不可以成为欧拉回路。
如果都是偶数,那么需要用最大流来判定。
最大流流的是什么?是反悔的边。
比如我们对应先前的无向边,我们任意选定了一个方向记录出度入度,那么另一个方向我们就需要连一条容量为1的边,代表我们有一次机会来返回。
然后对于出度比入度大的点我们可以将其连向汇点一条容量为出度入度之差一半的边。
入度比出度大的点我们可以从源点向他连一条容量为入度出度之差一半的边。
这样我们新建出来的图可以假装把它称为反悔图。
如果满流,显然我们可以保证这个欧拉回路存在,如果不满流那么说明这个欧拉回路不存在(无法流回,不知所措)。
代码:

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 1010
#define M 2010
#define LL L[i].l
#define RR L[i].r
#define C L[i].c1
#define CC L[i].c2
#define INF 0x3f3f3f3f
using namespace std;
int n,m;
int low,high;
struct line
{
    int l,r;
    int c1,c2;
    line(){}
    line(int _l,int _r,int _c1,int _c2):l(_l),r(_r),c1(_c1),c2(_c2){}
    friend istream& operator >> (istream &_,line &a)
    {scanf("%d%d%d%d",&a.l,&a.r,&a.c1,&a.c2);return _;}
    void update()
    {
        if(c1>c2)swap(c1,c2),swap(l,r);
        low=min(low,c1);
        high=max(high,c2);
    }
}L[M];
struct node
{
    int from,to,val;
    int next;
}edge[M<<2];
int head[N],cnt;
int in[N],out[N];
int dep[N],st,ed;
void init()
{
    low=0x3f3f3f3f,high=-1;
}
void init_before_check()
{
    memset(head,-1,sizeof(head));
    memset(in,0,sizeof(in));
    memset(out,0,sizeof(out));
    cnt=0,st=0,ed=n+1;
}
void edgeadd(int from,int to,int val)
{
    edge[cnt].from=from,edge[cnt].to=to;
    edge[cnt].val=val,edge[cnt].next=head[from];
    head[from]=cnt++;
}
bool bfs(int s,int e)
{
    memset(dep,0,sizeof(dep));
    queue<int>q;
    q.push(s);
    dep[s]=1;
    while(!q.empty())
    {
        int u=q.front();
        if(u==e)return 1;
        q.pop();
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int to=edge[i].to;
            if(dep[to]!=0||!edge[i].val)continue;
            dep[to]=dep[u]+1;
            q.push(to);
        }
    }
    return 0;
}
int dfs(int s,int max_vale)
{
    int ret=0;
    if(s==ed)return max_vale;
    for(int i=head[s];i!=-1;i=edge[i].next)
    {
        int to=edge[i].to;
        if(edge[i].val==0||dep[to]!=dep[s]+1)continue;
        int tmp=dfs(to,min(max_vale-ret,edge[i].val));
        edge[i].val-=tmp;
        edge[i^1].val+=tmp;
        ret+=tmp;
        if(ret==max_vale)return ret;
    }
    return ret;
}
bool if_has_odd()
{
    for(int i=1;i<=n;i++)
        if(abs(in[i]-out[i])&1)return 1;
    return 0;
}
bool check(int x)
{
    init_before_check();
    for(int i=1;i<=m;i++)
    {
        if(L[i].c2<=x)
            edgeadd(RR,LL,1),edgeadd(LL,RR,0);
        if(L[i].c1<=x)
            out[LL]++,in[RR]++;
    }
    if(if_has_odd())return 0;
    int judge=0;
    for(int i=1;i<=n;i++)
    {
        if(out[i]>in[i])
            edgeadd(i,ed,(out[i]-in[i])>>1),edgeadd(ed,i,0),judge+=(out[i]-in[i])>>1;
        else if(out[i]<in[i])
            edgeadd(st,i,(in[i]-out[i])>>1),edgeadd(i,st,0);
    }
    int ret=0;
    while(bfs(st,ed))
    {
        while(int t=dfs(st,INF))
        {
            ret+=t;
        }
    }
    return ret==judge;
}
int main()
{
    init();
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){cin>>L[i];L[i].update();}
    int l=low,r=high,ans=-1;
    while(l<=r)
    {
        int mid=(l+r)>>1;
        if(check(mid))ans=mid,r=mid-1;
        else l=mid+1;
    }
    printf(ans==-1?"NIE\n":"%d\n",ans);
}
<think>好的,用户的问题是关于如何替代`runtime.bridges.bridges.toArray`方法的实现。首先,我需要理解这个方法的上下文和用途。根据用户提供的引用内容,特别是引用[1]和[2],提到了`createBridge`方法以及`AndroidDebugBridge`类。看起来这可能与Android调试桥(ADB)相关,用于管理连接到ADB的桥接实例。 用户提到`runtime.bridges.bridges.toArray`,可能是在处理ADB桥接实例的集合,需要将集合转换为数组。`toArray`方法通常用于将集合(如List、Set)转换为数组。用户可能遇到了性能问题,或者该方法在某些环境下不可用,需要替代方案。 接下来,我需要考虑可能的替代方法。首先,如果使用的是Java集合框架,比如`ArrayList`,可以使用`toArray()`方法的不同重载版本。例如,使用`toArray(new Type[0])`,这在较新的Java版本中推荐使用,因为性能更好。另外,手动遍历集合并填充数组也是一种替代方法,尽管效率可能较低,但在某些情况下可能更灵活。 此外,需要考虑用户的具体场景。比如,是否在Android开发中处理ADB连接,或者在使用Flink时遇到隐式转换问题(引用[3])。不过用户的问题更偏向于Java集合操作,可能与ADB桥接管理相关。 还需要检查用户提供的引用内容是否有其他线索。引用[1]提到`createBridge()`方法会检查现有的ADB连接,引用[2]说明如何创建不链接到特定ADB可执行文件的新桥接。可能用户在处理桥接实例的集合时,需要将这些实例转换为数组进行操作,比如遍历或传递给需要数组的方法。 可能的解决方案包括使用Java 8的流API来转换为数组,或者使用第三方库如Guava或Apache Commons Collections。但需要确保这些替代方法与原有代码兼容,并且不会引入新的依赖。 另外,用户可能需要确保线程安全,特别是在多线程环境下操作桥接集合。因此,在转换数组时,可能需要同步块来保证数据的一致性。 总结,替代`toArray`的方法包括使用特定类型的数组初始化、手动遍历填充、流API转换,或者第三方库方法。需要根据具体的使用场景和代码环境选择最合适的方法,并注意线程安全和性能问题。</think>根据代码上下文分析,`runtime.bridges.bridges.toArray`可能涉及Android调试桥(ADB)的桥接实例管理。以下是可替代的三种实现方案: ### 方案一:类型安全数组转换(推荐) ```java AndroidDebugBridge[] bridgeArray = bridges.toArray(new AndroidDebugBridge[0]); ``` * 优势:JDK6+支持,避免强制类型转换错误 * 适用场景:需要精确控制数组类型时 ### 方案二:手动遍历填充 ```java AndroidDebugBridge[] bridgeArray = new AndroidDebugBridge[bridges.size()]; int index = 0; for (AndroidDebugBridge bridge : bridges) { bridgeArray[index++] = bridge; } ``` * 优势:避免并发修改异常 * 适用场景:需要遍历时进行额外逻辑处理 ### 方案三:Java Stream转换(JDK8+) ```java AndroidDebugBridge[] bridgeArray = bridges.stream() .toArray(AndroidDebugBridge[]::new); ``` * 优势:函数式编程风格 * 适用场景:需要链式处理集合元素时 ### 线程安全注意事项 若操作涉及多线程访问桥接集合,建议使用同步块: ```java synchronized (bridges) { AndroidDebugBridge[] bridgeArray = bridges.toArray(new AndroidDebugBridge[0]); // 后续操作 } ``` ### 扩展建议 1. 对于需要动态调整集合的场景,可参考`createBridge()`方法中的连接管理逻辑[^1] 2. 桥接实例创建可借鉴`AndroidDebugBridge`私有构造函数的设计模式[^2] 3. 集合操作可结合ADB客户端管理机制进行优化[^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值