10 条题解
-
1Pia LV 9 @ 2016-08-08 11:24:26
#include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<queue> using namespace std; const int maxn = 500000 + 5; const int INF = 1000000000; int n, l[10][505][505]; struct Edge { int from, to, dist; Edge (int from, int to, int dist) : from(from), to(to), dist(dist) {} }; struct HeapNode { int d, u; HeapNode (int d, int u) : d(d), u(u) {} bool operator < (const HeapNode& rhs) const { return d > rhs.d; } }; struct Dijkstra{ int n, m, d[maxn],G[250001][100],size[maxn]; vector<Edge> edges; bool done[maxn]; void init(int n){ this -> n = n; m = 0; memset(d, 0, sizeof(d)); memset(G, 0, sizeof(G)); edges.clear(); memset(size, 0, sizeof(size)); } void AddEdge(int from, int to, int dist){ edges.push_back(Edge{from, to, dist}); G[from][size[from]++] = m++; } void dijkstra(int s){ priority_queue<HeapNode> Q; for(int i = 0; i < n; i++) d[i] = INF; d[s] = 0; memset(done, 0, sizeof(done)); Q.push(HeapNode{0,s}); while(!Q.empty()){ HeapNode x = Q.top(); Q.pop(); int u = x.u; if(done[u]) continue; done[u] = 1; for(int i = 0; i < size[u]; i++){ Edge& e = edges[G[u][i]]; if(d[e.to] > d[u] + e.dist){ d[e.to] = d[u] + e.dist; Q.push(HeapNode{d[e.to], e.to}); } } } } }; Dijkstra solver; int cnt; int id[550][550]; int ID (int i, int j) { int& x = id[i][j]; if (x == 0) x = ++cnt; return x; } void init(){ cin >> n; for(int k = 0; k < 4; k++) for(int i = 0; i < n+(k+1)%2; i++) for(int j = 0; j < n+k%2; j++) cin >> l[k][i][j]; solver.init(n*n+2); cnt = 0; memset(id, 0, sizeof(id)); for(int i = 0; i < n; i++) for(int j = 0; j < n; j++){ int idx = ID(i,j); if(j > 0) solver.AddEdge(idx,ID(i,j-1),l[3][i][j]); if(j < n-1) solver.AddEdge(idx,ID(i,j+1),l[1][i][j+1]); if(i > 0) solver.AddEdge(idx,ID(i-1,j),l[0][i][j]); if(i < n-1) solver.AddEdge(idx,ID(i+1,j),l[2][i+1][j]); } for(int i = 0; i < n; i++){ solver.AddEdge(0,ID(i,0),l[1][i][0]); solver.AddEdge(0,ID(n-1,i),l[0][n][i]); solver.AddEdge(ID(0,i),cnt+1,l[0][0][i]); solver.AddEdge(ID(i,n-1),cnt+1,l[1][i][n]); } } int main(){ init(); solver.dijkstra(0); cout << solver.d[cnt+1]; return 0; }
-
02016-08-08 08:29:16@
2006年ACM北京的一道题,不过那边是一个三角形一个结点
```c++
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;const int INF = 1000000000;
const int maxsize = 500 + 10;
const int maxn = 500 * 500 + 100;struct Edge {
int from, to, dist;
Edge (int from, int to, int dist) : from(from), to(to), dist(dist) {}
};struct HeapNode {
int d, u;
HeapNode (int d, int u) : d(d), u(u) {}
bool operator < (const HeapNode& rhs) const {
return d > rhs.d;
}
};struct Dijkstra {
int n, m;
vector<int> G[maxn];
vector<Edge> edges;
int d[maxn], p[maxn];
bool done[maxn];void init (int n) {
this->n = n;
for (int i = 0; i < n; i++) G[i].clear();
edges.clear();
}void AddEdge (int from, int to, int dist) {
edges.push_back(Edge(from, to, dist));
m = edges.size();
G[from].push_back(m-1);
}void dijkstra (int s) {
priority_queue<HeapNode> Q;
memset(done, 0, sizeof(done));
for (int i = 0; i < n; i++) d[i] = INF;
d[s] = 0;
Q.push(HeapNode(d[s], s));
while (!Q.empty()) {
HeapNode x = Q.top(); Q.pop();
int u = x.u;
if (done[u]) continue;
done[u] = true;
for (int i = 0; i < G[u].size(); i++) {
Edge& e = edges[G[u][i]];
if (d[e.to] > d[u] + e.dist) {
d[e.to] = d[u] + e.dist;
p[e.to] = G[u][i];
Q.push(HeapNode(d[e.to], e.to));
}
}
}
}
};Dijkstra solver;
int cnt;
int id[maxsize][maxsize];
int ID (int i, int j) {
int& x = id[i][j];
if (x == 0) x = ++cnt;
return x;
}int n;
int flow[maxsize][maxsize][4];int main ()
{
// freopen("in.txt", "r", stdin);
cin >> n;
n++;
solver.init((n-1)*(n-1)+2);
for (int i = 0; i < n; i++) for (int j = 0; j < n-1; j++) scanf("%d", &flow[i][j][0]); //right
for (int i = 0; i < n-1; i++) for (int j = 0; j < n; j++) scanf("%d", &flow[i][j][1]); //down
for (int i = 0; i < n; i++) for (int j = 0; j < n-1; j++) scanf("%d", &flow[i][j][2]); //left
for (int i = 0; i < n-1; i++) for (int j = 0; j < n; j++) scanf("%d", &flow[i][j][3]); //upcnt = 0;
memset(id, 0, sizeof(id));
for (int i = 0; i < n-1; i++) for (int j = 0; j < n-1; j++) {
int idn = ID(i, j);
if (i > 0) solver.AddEdge(idn, ID(i-1, j), flow[i][j][0]);
if (i < n-2) solver.AddEdge(idn, ID(i+1, j), flow[i+1][j][2]);if (j > 0) solver.AddEdge(idn, ID(i, j-1), flow[i][j][3]);
if (j < n-2) solver.AddEdge(idn, ID(i, j+1), flow[i][j+1][1]);
}for (int i = 0; i < n-1; i++) {
solver.AddEdge(0, ID(i, 0), flow[i][0][1]);
solver.AddEdge(0, ID(n-2, i), flow[n-1][i][0]);solver.AddEdge(ID(0, i), cnt+1, flow[0][i][0]);
solver.AddEdge(ID(i, n-2), cnt+1, flow[i][n-1][1]);
}solver.dijkstra(0);
cout << solver.d[cnt+1];return 0;
}
``` -
02015-07-01 10:40:56@
AC
const maxn=2000000;
type node=record
from,go,next,w:longint;
end;
var i,j,n,cnt,tot,t,x,s,l,r,y:longint;
head,d,a,p:array[0..maxn] of longint;
v:array[0..maxn] of boolean;
e:array[0..maxn] of node;
num:array[0..600,0..600] of longint;
procedure insert(x,y,z:longint);
begin
inc(tot);
e[tot].from:=x;e[tot].go:=y;e[tot].w:=z;e[tot].next:=head[x];head[x]:=tot;
end;
procedure up(i:longint);
var t:longint;
begin
while (i>1) and (d[a[i]]<d[a[i>>1]]) do
begin
t:=a[i];a[i]:=a[i>>1];a[i>>1]:=t;
p[a[i]]:=i;p[a[i>>1]]:=i>>1;
i:=i>>1;
end;
end;
procedure down(i:longint);
var t,j:longint;
begin
j:=i<<1;
if (j<cnt) and (d[a[j+1]]<d[a[j]]) then inc(j);
while (j<=cnt) and (d[a[j]]<d[a[i]]) do
begin
t:=a[i];a[i]:=a[j];a[j]:=t;
p[a[i]]:=i;p[a[j]]:=j;
i:=j;j:=j<<1;
if (j<cnt) and (d[a[j+1]]<d[a[j]]) then inc(j);
end;
end;
procedure dijkstra;
begin
fillchar(d,sizeof(d),60);
fillchar(v,sizeof(v),false);
d[s]:=0;cnt:=0;
for i:=0 to n*n+1 do begin inc(cnt);a[cnt]:=i;p[i]:=cnt;up(cnt);end;
for j:=1 to n*n+1 do
begin
x:=a[1];a[1]:=a[cnt];dec(cnt);down(1);
v[x]:=true;
i:=head[x];
while i<>0 do
begin
y:=e[i].go;
if not(v[y]) and (d[x]+e[i].w<d[y]) then
begin
d[y]:=d[x]+e[i].w;
up(p[y]);
end;
i:=e[i].next;
end;
end;
end;
procedure init;
begin
readln(n);s:=0;t:=n*n+1;
for i:=1 to n do for j:=1 to n do num[i,j]:=(i-1)*n+j;
for i:=1 to n+1 do
for j:=1 to n do
begin
readln(x);
if i=1 then insert(num[i,j],t,x)
else if i=n+1 then insert(s,num[i-1,j],x)
else insert(num[i,j],num[i-1,j],x);
end;
for i:=1 to n do
for j:=1 to n+1 do
begin
readln(x);
if j=1 then insert(s,num[i,j],x)
else if j=n+1 then insert(num[i,j-1],t,x)
else insert(num[i,j-1],num[i,j],x);
end;
for i:=1 to n+1 do
for j:=1 to n do
begin
readln(x);
if i=1 then insert(t,num[i,j],x)
else if i=n+1 then insert(num[i-1,j],s,x)
else insert(num[i-1,j],num[i,j],x);
end;
for i:=1 to n do
for j:=1 to n+1 do
begin
readln(x);
if j=1 then insert(num[i,j],s,x)
else if j=n+1 then insert(t,num[i,j-1],x)
else insert(num[i,j],num[i,j-1],x);
end;
end;
procedure main;
begin
dijkstra;
writeln(d[t]);
end;
begin
init;
main;
end. -
02014-06-12 11:06:08@
写spfa其实只要加上 if(dis[p]+side[i].c>dis[T] && dis[T]!=-1) continue;
这句优化就可以过了(如果常数比较正常的话) -
02014-06-03 13:50:17@
Binary Heap的dijkstra果然还是比lll+slf的spfa快一吨的速度
-
02014-06-02 21:29:02@
-
02014-02-16 16:31:07@
编译成功
测试数据 #0: Accepted, time = 0 ms, mem = 49620 KiB, score = 10
测试数据 #1: Accepted, time = 0 ms, mem = 49616 KiB, score = 10
测试数据 #2: Accepted, time = 0 ms, mem = 49616 KiB, score = 10
测试数据 #3: Accepted, time = 0 ms, mem = 49616 KiB, score = 10
测试数据 #4: Accepted, time = 0 ms, mem = 49616 KiB, score = 10
测试数据 #5: Accepted, time = 0 ms, mem = 49620 KiB, score = 10
测试数据 #6: Accepted, time = 0 ms, mem = 49616 KiB, score = 10
测试数据 #7: Accepted, time = 0 ms, mem = 49612 KiB, score = 10
测试数据 #8: Accepted, time = 452 ms, mem = 49616 KiB, score = 10
测试数据 #9: Accepted, time = 374 ms, mem = 49620 KiB, score = 10
Accepted, time = 826 ms, mem = 49620 KiB, score = 100
代码
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<queue>
#include<algorithm>using namespace std;
const long long inf=(long long)1<<40;
const int maxn=500+10;struct Tree
{
long long dis;
int tp;
}tree[maxn*maxn*2];struct node
{
int to,flow,mf;
}edge[maxn*maxn*4*2];long long dans[maxn*maxn*2];
int wh[maxn*maxn*2];
int n,h[maxn*maxn],nex[maxn*maxn*4*2];
int top=-1,dis[maxn*maxn],tail;
int tt,ss;void tree_swap(Tree& a,Tree& b)
{
Tree c=a; a=b; b=c;
return;
}int rm(int x,int y)
{
if(x>n||y<1) return ss;
if(x<1||y>n) return tt;
return n*(y-1)+x;
}void addedge(int x,int y,int flow)
{
edge[++top]=(node){y,0,flow};
nex[top]=h[x]; h[x]=top;
return;
}void init(void)
{
cin>>n;
memset(h,-1,sizeof(h));
int flow;
ss=0; tt=rm(n,n)+1;
for(int i=1;i<=n+1;++i)
{
for(int k=1;k<=n;++k)
{
scanf("%d",&flow);
addedge(rm(i,k),rm(i-1,k),flow);
}
}
for(int i=1;i<=n;++i)
{
for(int k=1;k<=n+1;++k)
{
scanf("%d",&flow);
addedge(rm(i,k-1),rm(i,k),flow);
}
}
for(int i=1;i<=n+1;++i)
{
for(int k=2;k<=n+1;++k)
{
scanf("%d",&flow);
addedge(rm(i-1,k-1),rm(i,k-1),flow);
}
}
for(int i=2;i<=n+1;++i)
{
for(int k=1;k<=n+1;++k)
{
scanf("%d",&flow);
addedge(rm(i-1,k),rm(i-1,k-1),flow);
}
}
return;
}void up(int x)
{
while(x>1)
{
int k=x/2;
if(tree[k].dis>tree[x].dis)
{
wh[tree[k].tp]=x;
wh[tree[x].tp]=k;
tree_swap(tree[k],tree[x]);
x=k;
}
else break;
}
return;
}void down(int x)
{
while(x<=(tail/2))
{
int k=x*2;
if(k+1<=tail&&tree[k+1].dis<tree[k].dis) ++k;
if(tree[k].dis<tree[x].dis)
{
wh[tree[k].tp]=x;
wh[tree[x].tp]=k;
tree_swap(tree[k],tree[x]);
x=k;
}
else break;
}
return;
}void dja(void)
{
bool vis[maxn*maxn*2];
memset(vis,0,sizeof(vis));
for(int i=1;i<=tt+1;++i)
{
tree[i].dis=inf;
tree[i].tp=i-1;
wh[i-1]=i;
}
tail=tt+1;
tree[1].dis=0;
for(int i=1;i<=tt+1;++i)
{
Tree now=tree[1];
vis[now.tp]=true; dans[now.tp]=now.dis;
int k=h[now.tp];
while(k!=-1)
{
node e=edge[k];
if(vis[e.to]==false&&tree[wh[e.to]].dis>e.mf+now.dis)
{
tree[wh[e.to]].dis=e.mf+now.dis;
up(wh[e.to]);
}
k=nex[k];
}
tree[1]=tree[tail--];
down(1);
}
cout<<dans[tt];
return;
}int main(void)
{
init();
dja();
return 0;
} -
02014-02-16 16:29:42@
###Block code
编译成功测试数据 #0: Accepted, time = 0 ms, mem = 49620 KiB, score = 10
测试数据 #1: Accepted, time = 0 ms, mem = 49616 KiB, score = 10
测试数据 #2: Accepted, time = 0 ms, mem = 49616 KiB, score = 10
测试数据 #3: Accepted, time = 0 ms, mem = 49616 KiB, score = 10
测试数据 #4: Accepted, time = 0 ms, mem = 49616 KiB, score = 10
测试数据 #5: Accepted, time = 0 ms, mem = 49620 KiB, score = 10
测试数据 #6: Accepted, time = 0 ms, mem = 49616 KiB, score = 10
测试数据 #7: Accepted, time = 0 ms, mem = 49612 KiB, score = 10
测试数据 #8: Accepted, time = 452 ms, mem = 49616 KiB, score = 10
测试数据 #9: Accepted, time = 374 ms, mem = 49620 KiB, score = 10
Accepted, time = 826 ms, mem = 49620 KiB, score = 100
代码
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<queue>
#include<algorithm>using namespace std;
const long long inf=(long long)1<<40;
const int maxn=500+10;struct Tree
{
long long dis;
int tp;
}tree[maxn*maxn*2];struct node
{
int to,flow,mf;
}edge[maxn*maxn*4*2];long long dans[maxn*maxn*2];
int wh[maxn*maxn*2];
int n,h[maxn*maxn],nex[maxn*maxn*4*2];
int top=-1,dis[maxn*maxn],tail;
int tt,ss;void tree_swap(Tree& a,Tree& b)
{
Tree c=a; a=b; b=c;
return;
}int rm(int x,int y)
{
if(x>n||y<1) return ss;
if(x<1||y>n) return tt;
return n*(y-1)+x;
}void addedge(int x,int y,int flow)
{
edge[++top]=(node){y,0,flow};
nex[top]=h[x]; h[x]=top;
return;
}void init(void)
{
cin>>n;
memset(h,-1,sizeof(h));
int flow;
ss=0; tt=rm(n,n)+1;
for(int i=1;i<=n+1;++i)
{
for(int k=1;k<=n;++k)
{
scanf("%d",&flow);
addedge(rm(i,k),rm(i-1,k),flow);
}
}
for(int i=1;i<=n;++i)
{
for(int k=1;k<=n+1;++k)
{
scanf("%d",&flow);
addedge(rm(i,k-1),rm(i,k),flow);
}
}
for(int i=1;i<=n+1;++i)
{
for(int k=2;k<=n+1;++k)
{
scanf("%d",&flow);
addedge(rm(i-1,k-1),rm(i,k-1),flow);
}
}
for(int i=2;i<=n+1;++i)
{
for(int k=1;k<=n+1;++k)
{
scanf("%d",&flow);
addedge(rm(i-1,k),rm(i-1,k-1),flow);
}
}
return;
}void up(int x)
{
while(x>1)
{
int k=x/2;
if(tree[k].dis>tree[x].dis)
{
wh[tree[k].tp]=x;
wh[tree[x].tp]=k;
tree_swap(tree[k],tree[x]);
x=k;
}
else break;
}
return;
}void down(int x)
{
while(x<=(tail/2))
{
int k=x*2;
if(k+1<=tail&&tree[k+1].dis<tree[k].dis) ++k;
if(tree[k].dis<tree[x].dis)
{
wh[tree[k].tp]=x;
wh[tree[x].tp]=k;
tree_swap(tree[k],tree[x]);
x=k;
}
else break;
}
return;
}void dja(void)
{
bool vis[maxn*maxn*2];
memset(vis,0,sizeof(vis));
for(int i=1;i<=tt+1;++i)
{
tree[i].dis=inf;
tree[i].tp=i-1;
wh[i-1]=i;
}
tail=tt+1;
tree[1].dis=0;
for(int i=1;i<=tt+1;++i)
{
Tree now=tree[1];
vis[now.tp]=true; dans[now.tp]=now.dis;
int k=h[now.tp];
while(k!=-1)
{
node e=edge[k];
if(vis[e.to]==false&&tree[wh[e.to]].dis>e.mf+now.dis)
{
tree[wh[e.to]].dis=e.mf+now.dis;
up(wh[e.to]);
}
k=nex[k];
}
tree[1]=tree[tail--];
down(1);
}
cout<<dans[tt];
return;
}int main(void)
{
init();
dja();
return 0;
} -
02014-02-16 16:22:44@
看了08年周冬集训队论文才过的,膜拜大牛……
平面图转对偶图,然后求最短路
dja+heap
编译成功测试数据 #0: Accepted, time = 0 ms, mem = 49620 KiB, score = 10
测试数据 #1: Accepted, time = 0 ms, mem = 49616 KiB, score = 10
测试数据 #2: Accepted, time = 0 ms, mem = 49616 KiB, score = 10
测试数据 #3: Accepted, time = 0 ms, mem = 49616 KiB, score = 10
测试数据 #4: Accepted, time = 0 ms, mem = 49616 KiB, score = 10
测试数据 #5: Accepted, time = 0 ms, mem = 49620 KiB, score = 10
测试数据 #6: Accepted, time = 0 ms, mem = 49616 KiB, score = 10
测试数据 #7: Accepted, time = 0 ms, mem = 49612 KiB, score = 10
测试数据 #8: Accepted, time = 452 ms, mem = 49616 KiB, score = 10
测试数据 #9: Accepted, time = 374 ms, mem = 49620 KiB, score = 10
Accepted, time = 826 ms, mem = 49620 KiB, score = 100
代码
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<queue>
#include<algorithm>using namespace std;
const long long inf=(long long)1<<40;
const int maxn=500+10;struct Tree
{
long long dis;
int tp;
}tree[maxn*maxn*2];struct node
{
int to,flow,mf;
}edge[maxn*maxn*4*2];long long dans[maxn*maxn*2];
int wh[maxn*maxn*2];
int n,h[maxn*maxn],nex[maxn*maxn*4*2];
int top=-1,dis[maxn*maxn],tail;
int tt,ss;void tree_swap(Tree& a,Tree& b)
{
Tree c=a; a=b; b=c;
return;
}int rm(int x,int y)
{
if(x>n||y<1) return ss;
if(x<1||y>n) return tt;
return n*(y-1)+x;
}void addedge(int x,int y,int flow)
{
edge[++top]=(node){y,0,flow};
nex[top]=h[x]; h[x]=top;
return;
}void init(void)
{
cin>>n;
memset(h,-1,sizeof(h));
int flow;
ss=0; tt=rm(n,n)+1;
for(int i=1;i<=n+1;++i)
{
for(int k=1;k<=n;++k)
{
scanf("%d",&flow);
addedge(rm(i,k),rm(i-1,k),flow);
}
}
for(int i=1;i<=n;++i)
{
for(int k=1;k<=n+1;++k)
{
scanf("%d",&flow);
addedge(rm(i,k-1),rm(i,k),flow);
}
}
for(int i=1;i<=n+1;++i)
{
for(int k=2;k<=n+1;++k)
{
scanf("%d",&flow);
addedge(rm(i-1,k-1),rm(i,k-1),flow);
}
}
for(int i=2;i<=n+1;++i)
{
for(int k=1;k<=n+1;++k)
{
scanf("%d",&flow);
addedge(rm(i-1,k),rm(i-1,k-1),flow);
}
}
return;
}void up(int x)
{
while(x>1)
{
int k=x/2;
if(tree[k].dis>tree[x].dis)
{
wh[tree[k].tp]=x;
wh[tree[x].tp]=k;
tree_swap(tree[k],tree[x]);
x=k;
}
else break;
}
return;
}void down(int x)
{
while(x<=(tail/2))
{
int k=x*2;
if(k+1<=tail&&tree[k+1].dis<tree[k].dis) ++k;
if(tree[k].dis<tree[x].dis)
{
wh[tree[k].tp]=x;
wh[tree[x].tp]=k;
tree_swap(tree[k],tree[x]);
x=k;
}
else break;
}
return;
}void dja(void)
{
bool vis[maxn*maxn*2];
memset(vis,0,sizeof(vis));
for(int i=1;i<=tt+1;++i)
{
tree[i].dis=inf;
tree[i].tp=i-1;
wh[i-1]=i;
}
tail=tt+1;
tree[1].dis=0;
for(int i=1;i<=tt+1;++i)
{
Tree now=tree[1];
vis[now.tp]=true; dans[now.tp]=now.dis;
int k=h[now.tp];
while(k!=-1)
{
node e=edge[k];
if(vis[e.to]==false&&tree[wh[e.to]].dis>e.mf+now.dis)
{
tree[wh[e.to]].dis=e.mf+now.dis;
up(wh[e.to]);
}
k=nex[k];
}
tree[1]=tree[tail--];
down(1);
}
cout<<dans[tt];
return;
}int main(void)
{
init();
dja();
return 0;
} -
02013-12-17 12:39:43@
把最小割转最短路,,。。。
SPFA+SLF+LLL目测还是略慢,比DJ慢了不少。。。:编译成功
测试数据 #0: Accepted, time = 0 ms, mem = 3764 KiB, score = 10
测试数据 #1: Accepted, time = 0 ms, mem = 3768 KiB, score = 10
测试数据 #2: Accepted, time = 0 ms, mem = 3788 KiB, score = 10
测试数据 #3: Accepted, time = 0 ms, mem = 3792 KiB, score = 10
测试数据 #4: Accepted, time = 0 ms, mem = 3800 KiB, score = 10
测试数据 #5: Accepted, time = 0 ms, mem = 3912 KiB, score = 10
测试数据 #6: Accepted, time = 15 ms, mem = 3960 KiB, score = 10
测试数据 #7: Accepted, time = 0 ms, mem = 4012 KiB, score = 10
测试数据 #8: Accepted, time = 1482 ms, mem = 42956 KiB, score = 10
测试数据 #9: Accepted, time = 1872 ms, mem = 42968 KiB, score = 10
Accepted, time = 3369 ms, mem = 42968 KiB, score = 100#include <cstdio>
#include <algorithm>
#include <cstring>
#include <deque>using namespace std ;
#define MAXN 510
#define inf 0x7fffffff
#define MAXV MAXN * MAXNstruct edge {
edge *next ;
int t , d ;
} *head[ MAXV ] ;void AddEdge( int s , int t , int d ) {
edge *p = new( edge ) ;
p -> t = t , p -> d = d , p -> next = head[ s ] ;
head[ s ] = p ;
}int node[ MAXN ][ MAXN ] , S , T , n , V = 0 ;
int dist[ MAXV ] ; bool f[ MAXV ] ;
deque< int >Q ;int spfa( ) {
for ( int i = 0 ; i ++ < V ; ) dist[ i ] = inf , f[ i ] = false ;
Q.clear( ) ; long long sum = 0 ;
Q.push_back( S ) , dist[ S ] = 0 , f[ S ] = true ;
while ( ! Q.empty( ) ) {
while ( dist[ Q.front( ) ] > sum / Q.size( ) + 1 ) Q.push_back( Q.front( ) ) , Q.pop_front( ) ;
int v = Q.front( ) ; Q.pop_front( ) ; f[ v ] = false ; sum -= dist[ v ] ;
if ( dist[ v ] > dist[ T ] ) continue ;
for ( edge *p = head[ v ] ; p ; p = p -> next ) if ( dist[ p -> t ] > dist[ v ] + p -> d ) {
if ( f[ p -> t ] ) sum -= dist[ p -> t ] ;
dist[ p -> t ] = dist[ v ] + p -> d ;
sum += dist[ p -> t ] ;
if ( ! f[ p -> t ] ) {
f[ p -> t ] = true ;
if ( Q.empty( ) ) Q.push_back( p -> t ) ;
else if ( dist[ p -> t ] < dist[ Q.front( ) ] ) Q.push_front( p -> t ) ;
else Q.push_back( p -> t ) ;
}
}
}
return dist[ T ] ;
}int main( ) {
scanf( "%d" , &n ) ;
S = ++ V , T = ++ V ;
for ( int i = 0 ; i ++ < n ; ) for ( int j = 0 ; j ++ < n ; ) node[ i ][ j ] = ++ V ;
for ( int i = 0 ; i ++ < n ; ) {
int x ; scanf( "%d" , &x ) ;
AddEdge( node[ 1 ][ i ] , T , x ) ;
}
for ( int i = 0 ; i ++ < n - 1 ; ) {
for ( int j = 0 ; j ++ < n ; ) {
int x ; scanf( "%d" , &x ) ;
AddEdge( node[ i + 1 ][ j ] , node[ i ][ j ] , x ) ;
}
}
for ( int i = 0 ; i ++ < n ; ) {
int x ; scanf( "%d" , &x ) ;
AddEdge( S , node[ n ][ i ] , x ) ;
}
for ( int i = 0 ; i++ < n ; ) {
int x ; scanf( "%d" , &x ) ; AddEdge( S , node[ i ][ 1 ] , x ) ;
for ( int j = 0 ; j ++ < n - 1 ; ) scanf( "%d" , &x ) , AddEdge( node[ i ][ j ] , node[ i ][ j + 1 ] , x ) ;
scanf( "%d" , &x ) ; AddEdge( node[ i ][ n ] , T , x ) ;
}
for ( int i = 0 ; i ++ < n ; ) {
int x ; scanf( "%d" , &x ) ;
}
for ( int i = 0 ; i ++ < n - 1 ; ) for ( int j = 0 ; j ++ < n ; ) {
int x ; scanf( "%d" , &x ) ; AddEdge( node[ i ][ j ] , node[ i + 1 ][ j ] , x ) ;
}
for ( int i = 0 ; i ++ < n ; ) {
int x ; scanf( "%d" , &x ) ;
}
for ( int i = 0 ; i ++ < n ; ) {
int x ; scanf( "%d" , &x ) ;
for ( int j = 0 ; j ++ < n - 1 ; ) scanf( "%d" , &x ) , AddEdge( node[ i ][ j + 1 ] , node[ i ][ j ] , x ) ;
scanf( "%d" , &x ) ;
}
printf( "%d\n" , spfa( ) ) ;
return 0 ;
}
- 1