Secret Milking Machine POJ - 2455

点击打开链接

二分最大边 记为lim 不超过lim的边容量记为1 否则记为0 再抽象一个源点 从源点到1的容量为题目所给的t 然后以此建图 看是否满流

感觉网络流的抽象建图很关键 这道题看了别人的建图才会的...

符合条件就是1 即存在 反之就是0 即不存在 这样就把一个记录路径长度的图转化为记录路径是否可行的图 每增广一次图中就少一条路 长知识了!

 

#include <stdio.h>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 1e9

struct node1
{
    int u;
    int v;
    int w;
};

struct node2
{
    int v;
    int w;
    int next;
};

node1 pree[80010];
node2 edge[160010];
int first[210],dis[210],gap[210],cur[210],pre[210];
int n,m,t,num,sum,ans,ss,ee;

void binsearch(int l,int r);
void build(int lim);
void addedge(int u,int v,int w);
void isap();
void bfs();

int main()
{
    int i,u,v,w,minn,maxx;
    while(scanf("%d%d%d",&n,&m,&t)!=EOF)
    {
        num=0,minn=N,maxx=0;
        for(i=1;i<=m;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            num++;
            pree[num].u=u;
            pree[num].v=v;
            pree[num].w=w;
            num++;
            pree[num].u=v;
            pree[num].v=u;
            pree[num].w=w;
            if(w<minn) minn=w;
            if(w>maxx) maxx=w;
        }
        binsearch(minn,maxx);
        printf("%d\n",ans);
    }
    return 0;
}

void binsearch(int l,int r)
{
    int lim;
    ans=r;
    while(l<=r)
    {
        lim=(l+r)/2;
        build(lim);
        isap();
        if(sum>=t)
        {
            r=lim-1;
            ans=lim;
        }
        else
        {
            l=lim+1;
        }
    }
    return;
}

void build(int lim)
{
    int i;
    memset(first,-1,sizeof(first));
    num=0,ss=n+1,ee=n;
    addedge(ss,1,t);
    addedge(1,ss,0);
    for(i=1;i<=m*2;i++)
    {
        if(pree[i].w<=lim)
        {
            addedge(pree[i].u,pree[i].v,1);
            addedge(pree[i].v,pree[i].u,0);
        }
        else
        {
            addedge(pree[i].u,pree[i].v,0);
        }
    }
    return;
}

void addedge(int u,int v,int w)
{
    edge[num].v=v;
    edge[num].w=w;
    edge[num].next=first[u];
    first[u]=num++;
    return;
}

void isap()
{
    int j,u,v,flow,minn;
    memcpy(cur,first,sizeof(first));
    memset(pre,-1,sizeof(pre));
    bfs();
    num=n+1,sum=0,u=ss,flow=N;
    while(dis[ss]<num)
    {
        int &i=cur[u];
        for(;i!=-1;i=edge[i].next)
        {
            v=edge[i].v;
            if(edge[i].w>0&&dis[v]+1==dis[u])
            {
                pre[v]=i;
                u=v,flow=min(flow,edge[i].w);
                if(u==ee)
                {
                    while(u!=ss)
                    {
                        j=pre[u];
                        edge[j].w-=flow;
                        edge[j^1].w+=flow;
                        u=edge[j^1].v;
                    }
                    sum+=flow,flow=N;
                }
                break;
            }
        }
        if(i==-1)
        {
            if(--gap[dis[u]]==0) break;
            cur[u]=first[u];
            minn=num-1;
            for(j=first[u];j!=-1;j=edge[j].next)
            {
                if(edge[j].w>0)
                {
                    minn=min(minn,dis[edge[j].v]);
                }
            }
            dis[u]=minn+1;
            gap[dis[u]]++;
            if(u!=ss)
            {
                u=edge[pre[u]^1].v;
            }
        }
    }
    return;
}

void bfs()
{
    queue <int> que;
    int i,u,v;
    memset(dis,-1,sizeof(dis));
    memset(gap,0,sizeof(gap));
    que.push(ee);
    dis[ee]=0;
    while(!que.empty())
    {
        u=que.front();
        que.pop();
        gap[dis[u]]++;
        for(i=first[u];i!=-1;i=edge[i].next)
        {
            v=edge[i].v;
            if(dis[v]==-1)
            {
                dis[v]=dis[u]+1;
                que.push(v);
            }
        }
    }
    return;
}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值