这道题挺不错的。。不难发现都是0和1 原题还有小数迷惑人2333(想想 如果这条边很优 为什么不干脆弄到1?)
然后很快就知道 其实就等于把图分成了割成了两块
那么这就是平面图的最小割了。。
我太菜了 后面就不会了
然后去研究了一下 其实就是平面图转对偶图求最短路 太强了 好劲啊
资料: http://blog.sina.com.cn/s/blog_60707c0f01011fnn.html
其实倒也没有卡spfa 只不过对spfa很不友善
于是我打了个dijkstra 好快啊。。
#include<bits/stdc++.h>
#define me(a,x) memset(a,x,sizeof a)
using namespace std;
const int N=251000;
inline int read()
{
char ch=getchar(); int x=0,f=1;
while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0'; ch=getchar();}
return x*f;
}
struct node{
int d,x;
friend bool operator <(const node &x,const node &y){return x.d>y.d;}
};
struct edge{int y,c,next;}a[N<<2]; int len,first[N];
void ins(int x,int y,int c){a[++len]=(edge){y,c,first[x]},first[x]=len;}
priority_queue<node>q; int d[N],s,t;
void dij()
{
me(d,63); d[s]=0;
q.push((node){0,s});
while(!q.empty())
{
node x=q.top(); q.pop();
if(d[x.x]<x.d)continue;
for(int k=first[x.x];k;k=a[k].next)
{
int y=a[k].y;
if(d[y]>d[x.x]+a[k].c)
{
d[y]=d[x.x]+a[k].c;
q.push((node){d[y],y});
}
}
}
}
int main()
{
int n=read(),i,j,c ;s=n*n+1,t=s+1;
for(i=1;i<=n;i++)c=read(),ins(i,t,c);
for(i=1;i<n;i++)for(j=1;j<=n;j++)c=read(),ins(i*n+j,(i-1)*n+j,c);
for(i=1;i<=n;i++)c=read(),ins(s,n*(n-1)+i,c);
for(i=1;i<=n;i++)
{
c=read(),ins(s,(i-1)*n+1,c);
for(j=1;j<n;j++)c=read(),ins((i-1)*n+j,(i-1)*n+j+1,c);
c=read(),ins(i*n,t,c);
}
for(i=1;i<=n;i++)c=read(),ins(t,i,c);
for(i=1;i<n;i++)for(j=1;j<=n;j++)c=read(),ins((i-1)*n+j,i*n+j,c);
for(i=1;i<=n;i++)c=read(),ins(n*(n-1)+i,s,c);
for(i=1;i<=n;i++)
{
c=read(),ins((i-1)*n+1,s,c);
for(j=1;j<n;j++)c=read(),ins((i-1)*n+j+1,(i-1)*n+j,c);
c=read(),ins(t,i*n,c);
}
dij();
printf("%d\n",d[t]);
return 0;
}