这题就是真正的费用流了,用 大屁 就算不超时,你也有个 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; }