BZOJ 2007: [Noi2010]海拔

来源:互联网 发布:电脑同声翻译软件 编辑:程序博客网 时间:2024/06/02 17:51

这道题挺不错的。。不难发现都是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;}
2 1