BZOJ 1927 [Sdoi2010]星际竞速

来源:互联网 发布:微信支付接口开发 php 编辑:程序博客网 时间:2024/05/29 03:26

费用流

我只是想考前复习一下费用流……

显然一个点只会进一次,出一次。那就考虑每一个点的出点抵达哪个点的入点。可以画成一个二分图的形式。一个特别操作的是可以直接跳到一个点上,那就建一个附加点使得所有出点连它,它连所有入点即可。

#include<cstdio>#include<cstring>#include<algorithm>#define N 1605#define M 15005#define cmin(u,v) ((u)>(v)?(u)=(v):0)using namespace std;namespace runzhe2000{    const int S = N-2, T = N-1, U = N-3, INF = 1<<29;    int n, m, ecnt = 1, last[N], q[N], dis[N], from[N], a[N], ans, inq[N];    struct edge{int next, to, flow, val;}e[M*2+N*8];    void addedge(int a, int b, int flow, int val)    {        e[++ecnt] = (edge){last[a], b, flow, val};        last[a] = ecnt;        e[++ecnt] = (edge){last[b], a, 0, -val};        last[b] = ecnt;    }    int EK()    {        memset(dis, 63, sizeof(dis));        dis[S] = 0; from[T] = 0; q[0] = S;        for(int head=0, tail=1;; head++)        {            if(head == N) head = 0;             if(head == tail) break;            int x = q[head]; inq[x] = 0;            for(int i = last[x]; i; i = e[i].next) if(e[i].flow)            {                int y = e[i].to;                if(dis[x] + e[i].val < dis[y])                {                    dis[y] = dis[x] + e[i].val;                    from[y] = i;                    if(!inq[y])q[tail++] = y, inq[y] = 1;                    if(tail == N) tail = 0;                }            }        }        if(!from[T]) return 0; int f = INF;        for(int i = from[T]; i; i = from[e[i^1].to]) cmin(f, e[i].flow); ans += f * dis[T];        for(int i = from[T]; i; i = from[e[i^1].to]) e[i].flow -= f, e[i^1].flow += f;        return 1;    }    void main()    {        scanf("%d%d",&n,&m);        for(int i = 1; i <= n; i++)         {            scanf("%d",&a[i]);            addedge(S, i, 1, 0);            addedge(i+n, T, 1, 0);            addedge(i, U, 1, 0);            addedge(U,i+n, 1, a[i]);        }        for(int i = 1, a, b, c; i <= m; i++)        {            scanf("%d%d%d",&a,&b,&c);            if(a > b) swap(a, b);            addedge(a, b+n, 1, c);        }        for(;EK(););        printf("%d\n",ans);    }}int main(){    runzhe2000::main();}
0 0
原创粉丝点击