hdu 3572 Task Schedule(sap)

本文深入探讨了路径查找问题中从使用EK算法导致超时(TLE)到采用SAP算法提升效率的过程。通过详细代码展示,展示了如何在解决特定类型的问题时选择更合适的算法以避免性能瓶颈。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这题开始用EK敲的,结果TLE到死,然后在网上看到说sap比EK要快,然后就各种搜sap算法,贴个代码在这,但是个模板吧。

#include<iostream>
#include<algorithm>
#include<string.h>
#include<stack>
#include<queue>
#include<math.h>
#include<cstdio>

#define mm(a,b) memset(a,b,sizeof(a))
using namespace std;

const int maxn=1111;
const int maxm=505000;
const int inf=0x7fffff;

struct Node
{
	int u,v,w;
	int next;
}edge[maxm];
int cur[maxn],pre[maxn];
int dis[maxn],gap[maxn];
int minf[maxn],head[maxn];
int idx;

void addEdge(int u, int v, int w)
{
    edge[idx].u=u;
    edge[idx].v=v;
    edge[idx].w=w;
    edge[idx].next=head[u];
    head[u]=idx++;

    edge[idx].u=v;
    edge[idx].v=u;
    edge[idx].w=0;
    edge[idx].next=head[v];
    head[v]=idx++;
}

int sap(int s, int t, int n)
{
    int max_flow=0,v,u=s;
    int id,mindis;
    minf[s]=inf;
    pre[s]=-1;
    mm(dis,0);
    mm(gap,0);
    gap[0]=n;
    for(int i=0;i<=n;++i) 
        cur[i]=head[i];
    while(dis[s]<n)
    {
        bool flag=false;
        if(u==t)
        {
            max_flow+=minf[t];
            for(v=pre[t];v!=-1;v=pre[v]) 
            {
                id=cur[v];
                edge[id].w-=minf[t];
                edge[id^1].w+=minf[t];
                minf[v]-=minf[t]; 
                if(edge[id].w==0) u=v; 
            }
        }
        for(id=cur[u];id!=-1;id=edge[id].next)
        {   
            v=edge[id].v;
            if(edge[id].w>0 && dis[u]==dis[v]+1) 
            {
                flag=true;
                pre[v]=u;
                cur[u]=id;
                minf[v]=min(minf[u],edge[id].w);
                u=v;
                break;
            }
        }
        if(flag==false)
        {
            if(--gap[dis[u]]==0) break; 
            mindis=n;
            cur[u]=head[u];
            for(id=head[u];id!=-1;id=edge[id].next)
            {
                v=edge[id].v;
                if(edge[id].w>0 && dis[v]<mindis)
                {
                    mindis=dis[v];
                    cur[u]=id; 
                }
            }
            dis[u]=mindis+1;
            gap[dis[u]]++;
            if(u!=s) u=pre[u]; 
        }
    }
    return max_flow;
}

int main()
{
    int t,n,m,pi,si,ei;
    int Max,sum,source,sink,vn;
    scanf("%d",&t);
    for(int cas=1;cas<=t;++cas)
    {
        idx=0;
        mm(head,-1);
        sum=0;
		source=0; 
		Max=0;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i)
        {
            scanf("%d%d%d",&pi,&si,&ei);
            sum+=pi;
            Max=max(Max,ei);
            addEdge(source,i,pi);
            for(int j=n+si;j<=n+ei;++j)
                addEdge(i,j,1);
        }
        sink=n+Max+1;
        vn=sink+1;
        for(int i=n+1;i<=n+Max;++i)
            addEdge(i, sink, m);
        printf("Case %d: ",cas);
        if(sap(source, sink, vn)==sum)
            puts("Yes");
        else puts("No");
    	puts("");
    }
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值