[hdu 3376]Matrix Again

这题就是真正的费用流了,用 大屁 就算不超时,你也有个 CE :数组 so large

拆点,费用取反,最大费用最大流即可了喵~

不过似乎这题很不兼容 dijkstra 的样子

就算用 spfa 重赋权把边权搞正后依然 TLE ,额不是说 dijstra 正权图最强么?

一定是我没有手写堆,一定是的……

 

#include <cstdio>

#include <cstring>

#include <queue>

#define min(x, y) ((x)<(y) ? (x):(y))

const int inf=0x7F7F7F7F;

const int sizeOfPoint=800008;

const int sizeOfEdge=8000008;



int n;

int V;

int S, T;

int a[666][666][2];

bool vis[sizeOfPoint];

int h[sizeOfPoint];

inline int getint();

inline void putint(int);



struct edge {int point, flow, cost; edge * next, * pair;};

edge memory[sizeOfEdge], * port=memory;

edge * e[sizeOfPoint];

inline void clear() {port=memory; memset(e, 0, sizeof e); memset(a, 0, sizeof a);}

inline edge * newedge(int point, int flow, int cost, edge * next)

{

    edge * ret=port++;

    ret->point=point; ret->flow=flow; ret->cost=cost; ret->next=next;

    return ret;

}

inline void link(int u, int v, int f, int c)

{

    e[u]=newedge(v, f, c, e[u]); e[v]=newedge(u, 0, -c, e[v]);

    e[u]->pair=e[v]; e[v]->pair=e[u];

}

inline bool spfa();

int aug(int, int);

inline int costflow();



int main()

{

    while (scanf("%d", &n)!=EOF)

    {

        clear();

        V=0;

        for (int i=1;i<=n;i++)

            for (int j=1;j<=n;j++)

            {

                a[i][j][0]=++V; a[i][j][1]=++V;

                link(a[i][j][0], a[i][j][1], 1, -getint());

            }



        link(a[1][1][0], a[1][1][1], 1, 0);

        link(a[n][n][0], a[n][n][1], 1, 0);

        S=1; T=V;

        for (int i=1;i<=n;i++)

            for (int j=1;j<=n;j++)

            {

                if (i<n) link(a[i][j][1], a[i+1][j][0], 1, 0);

                if (j<n) link(a[i][j][1], a[i][j+1][0], 1, 0);

            }

        putint(-costflow());

    }



    return 0;

}



inline int getint()

{

    register int num=0;

    register char ch;

    do ch=getchar(); while (ch<'0' || ch>'9');

    do num=num*10+ch-'0', ch=getchar(); while (ch>='0' && ch<='9');

    return num;

}

inline void putint(int num)

{

    char stack[15];

    register int top=0;

    for ( ;num;num/=10) stack[++top]=num%10+'0';

    for ( ;top;top--) putchar(stack[top]);

    putchar('\n');

}



inline bool spfa()

{

    static std::queue<int> q;

    static bool inque[sizeOfPoint];

    memset(h, 0x7F, sizeof h); h[T]=0;

    memset(inque, 0, sizeof inque);

    for (inque[T]=true, q.push(T);q.size();q.pop())

    {

        int u=q.front();

        inque[u]=false;

        for (edge * i=e[u];i;i=i->next) if (i->pair->flow && h[i->point]>h[u]+i->pair->cost)

        {

            h[i->point]=h[u]+i->pair->cost;

            q.push(i->point);

            if (!inque[i->point]) inque[i->point]=true, q.push(i->point);

        }

    }

    return h[S]<inf;

}

int aug(int u, int flow)

{

    int left=flow;

    if (u==T) return flow;

    vis[u]=true;

    for (edge * i=e[u];i;i=i->next) if (!vis[i->point] && i->flow && h[u]==h[i->point]+i->cost)

    {

        int temp=aug(i->point, min(left, i->flow));

        i->flow-=temp; i->pair->flow+=temp; left-=temp;

        if (!left) break;

    }

    vis[u]=false;

    return flow-left;

}

inline int costflow()

{

    int ret=0;

    while (spfa())

        ret+=h[S]*aug(S, inf);

    return ret;

}

 

你可能感兴趣的:(Matrix)