hdu 4280 最大流+优化

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int inf = 0x7fffffff;
struct node
{
    int u,v,next,c;
}edge[400000+5];
int head[100000+5],gap[100000+5];
int ei,st, en,n,m;
void add(int u, int v, int w)
{
    edge[ei].u = u; edge[ei].v = v; edge[ei].c = w,edge[ei].next = head[u]; head[u] = ei ++;
    edge[ei].u = v; edge[ei].v = u; edge[ei].c = 0; edge[ei].next = head[v]; head[v] = ei++;
}

int q[100000+5];
int d[100000+5];
void bfs()
{
    memset(d,-1,sizeof(d));
    memset(gap,0,sizeof(gap));
    gap[0] = 1;
    int qhead = 0, qrear = 0;
    d[en] = 0;
    q[qrear++] = en;
    int u,v;
    while(qhead < qrear)
    {
        u = q[qhead++];
        qhead %= 100005;
        for(int i = head[u]; i !=-1; i = edge[i].next)
        {
            v = edge[i].v;
            if(edge[i].c != 0 || d[v] != -1)  continue;
            q[qrear ++] = v;
            qrear %= 100005;
            ++gap[d[v] = d[u] +1];
        }
    }
}
int s[100000+5],cur[100000+5];
int sap()
{
    int res = 0;
    bfs();
    int top = 0;  int u = st,i;
    memcpy(cur, head,sizeof(head));
    while(1)
    {
        if(u == en)
        {
            int tem = inf, inser = n;
            for(i = 0; i != top; i++)
            {
                if(tem > edge[s[i]].c)
                {
                    tem  =edge[s[i]].c; inser = i;
                }
            }
            for(i = 0; i != top; ++i)
            {
                edge[s[i]].c -= tem;
                edge[s[i]^1].c += tem;
            }
            res += tem;
            top = inser;
            u = edge[s[top]].u;
        }

        if(u != en && gap[d[u] -1] == 0) break;

        for(i = cur[u]; i!= -1; i = edge[i].next)
        {
            if(edge[i].c != 0 && d[u] == d[edge[i].v] + 1) break;
        }

        if(i != -1)
        {
            cur[u] = i;
            s[top ++] = i;
            u = edge[i].v;
        }
        else
        {
            int min = n;
            for(i = head[u]; i != -1; i = edge[i].next)
            {
                if(edge[i].c == 0) continue;
                if(min > d[edge[i].v])
                {
                    min = d[edge[i].v];
                    cur[u] = i;
                }
            }
            -- gap[d[u]];
            ++ gap[d[u] = min + 1] ;
            if( u != st)
                u = edge[s[--top]].u;
        }
    }
    return res;
}
int main()
{
    int times;
    scanf("%d",×);
    while(times --)
    {
        scanf("%d%d",&n,&m);
        int l = inf ,r = -inf;
        for(int i = 1; i <= n; i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            if(x > r)
            {
                r = x; en = i;
            }
            if(x < l)
            {
                l = x; st = i;
            }
        }
        memset(head,-1,sizeof(head)); ei = 0;
        for(int i = 1; i <= m; i++)
        {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            add(a,b,c);
            add(b,a,c);
        }
        int ans = sap();
        printf("%d\n",ans);
    }
}

一开始没有用当前弧优化T了几发,然后改了又接着T。在vj上一直T,在HDU上倒是过了,也是迷。 然后把bfs里的stl改成手动队列,在vj上也过了。不过dinic不是这道题比较好的方法,只是刚好能卡过去。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define find_min(a,b) a<b?a:b
using namespace std;
int m,n;
struct node
{
    int v, w,next;
}edge[200000+5];
int head[100000+5],ei;
int dis[100000+5];
void add(int u, int v, int w)
{
   edge[ei].v = v;edge[ei].w = w; edge[ei].next = head[u];head[u] = ei ++;
   edge[ei].v = u;edge[ei].w = w; edge[ei].next = head[v];head[v] = ei++;
}
int sta, tai;
int bfs()
{
    memset(dis,-1,sizeof(dis));
    dis[sta] = 0;
    int q[200000+5];
    int qh = 0; int qt = 0;
    q[qt++] = sta;
    while(qh < qt)
    {
        int now = q[qh];
        if(now == tai) return 1;
        for(int i = head[now]; i != -1; i = edge[i].next)
        {
            int v = edge[i].v;
            if(dis[v]  == -1 && edge[i].w >0)
            {
                dis[v] = dis[now]+ 1;
                q[qt++] = v;
            }
        }
        qh ++;
    }
    return 0;
}
int find(int x,int low)
{
 int a = 0;
 if(x == tai) return low;
 for (int i =head[x]; i != -1 && a < low; i = edge[i].next)
 {
     int v = edge[i].v, cap = edge[i].w;
     if(edge[i].w > 0 && dis[v] == dis[x] + 1)
     {
         int te = find_min(edge[i].w,low - a);
         te = find(v,te);
         a += te;
         edge[i].w  -=  te;
         edge[i^1].w += te;
     }
 }
  if(!a) dis[x] = -2;
  return a;
}

int dinic(int s, int en)
{
    int ans = 0,tan;
    while(bfs())
    {
        while(tan = find(s,0x7fffffff)) ans += tan;
    }
    printf("%d\n",ans);
    return 1;
}

int main()
{
    int times;
    scanf("%d",×);
    while(times --)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        int max_x =-10000000- 5, min_x = 10000000+5;
        int maxid,minid;
        for(int i = 1; i <= n; i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            if(x < min_x)
            {
                min_x = x; minid = i;
            }
            if(x > max_x)
            {
                maxid = i; max_x = x;
            }
        }
        memset(head,-1,sizeof(head)); ei = 0;
        for(int i = 1; i <= m; i++)
        {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            add(a,b,c);
        }
        sta = minid; tai = maxid;
        dinic(minid,maxid);
    }
}

dinic在求最大流的算法中已经算是比较快的了,但是数据量大的情况下还是不够的,所以学习了一下sap,确实要快很多4000+就过题了。


猜你喜欢

转载自blog.csdn.net/zlatan10/article/details/76571494
今日推荐