HDU 4280 Island Transport(网络流,SAP)

解题思路:

建模很简单,不过以前一直用dinic,而这个题目数据偏大,用dinic超时了,据说没有可以卡住SAP的网络流,于是搞到了一套SAP的模版,过了,保存一下模版。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define LL long long
using namespace std;

const int MAXN=100010;//点数的最大值
const int MAXM=400010;//边数的最大值
const int INF=0x3f3f3f3f;

struct Node
{
    int from,to,next;
    int cap;
}edge[MAXM];
int tol;
int head[MAXN];
int dep[MAXN];
int gap[MAXN];//gap[x]=y :说明残留网络中dep[i]==x的个数为y

int n;//n是总的点的个数,包括源点和汇点

void init()
{
    tol=0;
    memset(head,-1,sizeof(head));
}

void AddEdge(int u,int v,int w)
{
    edge[tol].from=u;
    edge[tol].to=v;
    edge[tol].cap=w;
    edge[tol].next=head[u];
    head[u]=tol++;
    edge[tol].from=v;
    edge[tol].to=u;
    edge[tol].cap=0;
    edge[tol].next=head[v];
    head[v]=tol++;
}
void BFS(int start,int end)
{
    memset(dep,-1,sizeof(dep));
    memset(gap,0,sizeof(gap));
    gap[0]=1;
    int que[MAXN];
    int front,rear;
    front=rear=0;
    dep[end]=0;
    que[rear++]=end;
    while(front!=rear)
    {
        int u=que[front++];
        if(front==MAXN)front=0;
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if(dep[v]!=-1)continue;
            que[rear++]=v;
            if(rear==MAXN)rear=0;
            dep[v]=dep[u]+1;
            ++gap[dep[v]];
        }
    }
}
int SAP(int start,int end)
{
    int res=0;
    BFS(start,end);
    int cur[MAXN];
    int S[MAXN];
    int top=0;
    memcpy(cur,head,sizeof(head));
    int u=start;
    int i;
    while(dep[start]<n)
    {
        if(u==end)
        {
            int temp=INF;
            int inser;
            for(i=0;i<top;i++)
               if(temp>edge[S[i]].cap)
               {
                   temp=edge[S[i]].cap;
                   inser=i;
               }
            for(i=0;i<top;i++)
            {
                edge[S[i]].cap-=temp;
                edge[S[i]^1].cap+=temp;
            }
            res+=temp;
            top=inser;
            u=edge[S[top]].from;
        }
        if(u!=end&&gap[dep[u]-1]==0)//出现断层,无增广路
          break;
        for(i=cur[u];i!=-1;i=edge[i].next)
           if(edge[i].cap!=0&&dep[u]==dep[edge[i].to]+1)
             break;
        if(i!=-1)
        {
            cur[u]=i;
            S[top++]=i;
            u=edge[i].to;
        }
        else
        {
            int min=n;
            for(i=head[u];i!=-1;i=edge[i].next)
            {
                if(edge[i].cap==0)continue;
                if(min>dep[edge[i].to])
                {
                    min=dep[edge[i].to];
                    cur[u]=i;
                }
            }
            --gap[dep[u]];
            dep[u]=min+1;
            ++gap[dep[u]];
            if(u!=start)u=edge[S[--top]].from;
        }
    }
    return res;
}

int main()
{
    int T,N,M;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d%d", &N, &M);
        int Min = 100010;
        int Max = -100010;
        int u,v,w;
        n = N;
        init();
        int x, y;
        int s,t;
        for(int i=1;i<=N;i++)
        {
            scanf("%d%d", &x,&y);
            if(x < Min)
            {
                Min = x;
                s = i;
            }
            if(x > Max)
            {
                Max = x;
                t = i;
            }
        }
        for(int i=1;i<=M;i++)
        {
            scanf("%d%d%d", &u,&v,&w);
            AddEdge(u,v,w);
            AddEdge(v,u,w);
        }
        printf("%d\n", SAP(s,t));
    }
    return 0;
}
时间: 2025-01-04 16:10:04

HDU 4280 Island Transport(网络流,SAP)的相关文章

HDU 4280 Island Transport 网络流裸题

非递归版好像被卡掉了,其他2个板子都能过. #include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #include<vector> using namespace std; #define ll int const int MAXN = 100100;//点数的最大值 const int MAXM = 400010;//边数的最大值 const in

HDU 4280 Island Transport(网络流模板)

转载请注明出处:http://blog.csdn.net/u012860063 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4280 Problem Description In the vast waters far far away, there are many islands. People are living on the islands, and all the transport among the islands relies

Hdu 4280 Island Transport(最大流)

Island Transport Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 6217    Accepted Submission(s): 1965 Problem Description In the vast waters far far away, there are many islands. People are l

HDU 4280 Island Transport(无向图最大流)

HDU 4280:http://acm.hdu.edu.cn/showproblem.php?pid=4280 题意: 比较裸的最大流题目,就是这是个无向图,并且比较卡时间. 思路: 是这样的,由于是无向图,所以addedge 的反边容量直接设为原始流量.然后还可以优化搜索的方向,bfs可以从t到s跑,dfs可以从s到t跑,这样快. //#pragma GCC optimize(3) //#pragma comment(linker, "/STACK:102400000,102400000&qu

HDU - 4280 Island Transport(ISAP)

题目大意:要求你将游客从最东边送到最西边,反正边是双向的,没有差别了 解题思路:裸流 ISAP 8080MS #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <queue> using namespace std; #define N 100010 #define INF 0x3f3f3f3f struct Edge { in

hdu 4289 Control(网络流 最大流+拆点)(模板)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4289 Control Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1545    Accepted Submission(s): 677 Problem Description You, the head of Department o

HDU4280:Island Transport(最大流)

Island Transport Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 13187    Accepted Submission(s): 4156 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4280 Description: In the vast waters far f

HDU 4289 Control (网络流-最小割)

Control Problem Description You, the head of Department of Security, recently received a top-secret information that a group of terrorists is planning to transport some WMD 1 from one city (the source) to another one (the destination). You know their

HDU 1853Cyclic Tour(网络流之最小费用流)

题目地址:HDU1853 费用流果然好神奇..还可以用来判断环...如果每个点都是环的一部分而且每个点只能用到一次的话,那每个点的初度入度都是1,这就可以利用网络流来解决,只要拆点令其流量为1,就限制了每个点只能用一次,每次左边的连到右边的,就相当于左边点的一次初度和右边的点的一次入度,很容易想象出来.最后只要判断总流量是否为n即可,因为如果总流量为n的话,说明每个点都出了一次度,每个点都入了一次度,而且由于拆点的流量限制,充分说明了每个点的初度入度都是1.进而说明了每个点都在环里.然后输出最后