hdu-4280

//最大流优化,sap模板

 

//代码如下:

 

#include<stdio.h>
#include<string.h>
#include<queue>

using namespace std;

#define N 100010
#define M 400010
#define INF 0x3f3f3f3f

int from[M],to[M],next[M],cap[M],head[N],ant;

void init(){ ant=0;memset(head,-1,sizeof(head));}
void add(int a,int b,int c){
    to[ant]=b;
    cap[ant]=c;
    from[ant]=a;
    next[ant]=head[a];
    head[a]=ant++;

    to[ant]=a;
    cap[ant]=0;
    from[ant]=b;
    next[ant]=head[b];
    head[b]=ant++;
}

int dp[N],num[N];
void bfs(int s,int e){
    int u,i;
    memset(num,0,sizeof(num));
    memset(dp,32,sizeof(dp));
    queue<int> que;
    que.push(s);dp[s]=0;num[0]=1;
    while(!que.empty()){
        u=que.front();que.pop();
        for(i=head[u];i!=-1;i=next[i]){
            if(cap[i]>0) continue;
            if(dp[to[i]]>dp[u]+1){
                dp[to[i]]=dp[u]+1;
                que.push(to[i]);
                num[dp[to[i]]]++;
            }
        }
    }
}
int cur[N],pre[N];
int sap(int s,int e,int n){
    int i,x,ans=0,inf;
    bfs(e,s);x=s;
    memcpy(cur,head,sizeof(head));
    while(dp[s]<n){
        if(x==e){
            inf=INF;i=e;
            while(i!=s){
                if(cap[pre[i]]<=inf) x=from[pre[i]],inf=cap[pre[i]];
                i=from[pre[i]];
            }
            ans+=inf;i=e;
            while(i!=s){
                cap[pre[i]]-=inf;
                cap[pre[i]^1]+=inf;
                i=from[pre[i]];
            }
        }
        if(x!=e&&num[dp[x]-1]==0) break;
        for(i=cur[x];i!=-1;i=next[i]){
            if(dp[to[i]]+1==dp[x]&&cap[i]>0) break;
        }
        if(i!=-1){
            cur[x]=i;pre[to[i]]=i;x=to[i];
        }else {
            inf=n-1;
            if(--num[dp[x]]==0) break;
            for(i=head[x];i!=-1;i=next[i]){
                if(cap[i]>0&&dp[to[i]]<inf){
                    inf=dp[to[i]];cur[x]=i;
                }
            }
            num[dp[x]=inf+1]++;
            if(x!=s) x=from[pre[x]];
        }
    }
    return ans;
}

int main(){
    int T,cas,m,n,i,a,b,c,maxx,minx,s,e;
    scanf("%d",&T);
    for(cas=1;cas<=T;cas++){
        init();
        minx=INF;maxx=-INF;
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++){
            scanf("%d%d",&a,&b);
            if(a<=minx) minx=a,s=i;
            if(a>=maxx) maxx=a,e=i;
        }
        for(i=1;i<=m;i++){
            scanf("%d%d%d",&a,&b,&c);add(a,b,c);add(b,a,c);
        }
        printf("%d\n",sap(s,e,n));
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值