zoukankan      html  css  js  c++  java
  • bzoj 2007: [Noi2010]海拔【最小割+dijskstra】

    上来就跑3e5的最大流……脑子抽了
    很容易看出,每个地方的海拔都是0或1因为再高了没有意义,又,上去下来再上去没有意义,所以最后一定是从s连着一片0,剩下连着t一片1,然后有贡献的就是01交接的那些边
    跑个最小割就好了
    然而跑不过,考虑建对偶图,也就是网格的空当成一个点,然后这些点之间互相连边的权值为原图穿过他们的边的权值,建立一对原点汇点,分别连左下边界的新点和右上边界的新点,这样跑最短路就是最小割
    方便的建图是把所有边转90度就是新边

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    const int N=300005;
    int n,h[N],cnt,dis[N],id[505][505],tot,s,t;
    bool v[N];
    struct qwe
    {
    	int ne,to,va;
    }e[N*20];
    int read()
    {
        int r=0,f=1;
        char p=getchar();
        while(p>'9'||p<'0')
        {
            if(p=='-')
                f=-1;
            p=getchar();
        }
        while(p>='0'&&p<='9')
        {
            r=r*10+p-48;
            p=getchar();
        }
        return r*f;
    }
    void add(int u,int v,int w)
    {
        cnt++;
        e[cnt].ne=h[u];
        e[cnt].to=v;
        e[cnt].va=w;
        h[u]=cnt;
    }
    int main()
    {
    	n=read();
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=n;j++)
    			id[i][j]=++tot;
    	s=0,t=id[n][n]+1;
    	for(int i=1;i<=n+1;i++)
    		for(int j=1;j<=n;j++)
    		{
    			int x=read();
    			if(i==1)
    				add(id[i][j],t,x);
    			else if(i==n+1)
    				add(s,id[i-1][j],x);
    			else
    				add(id[i][j],id[i-1][j],x);
    		}
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=n+1;j++)
    		{
    			int x=read();
    			if(j==1)
    				add(s,id[i][j],x);
    			else if(j==n+1)
    				add(id[i][j-1],t,x);
    			else
    				add(id[i][j-1],id[i][j],x);
    		}
    	for(int i=1;i<=n+1;i++)
    		for(int j=1;j<=n;j++)
    		{
    			int x=read();
    			if(i==1)
    				add(t,id[i][j],x);
    			else if(i==n+1)
    				add(id[i-1][j],s,x);
    			else
    				add(id[i-1][j],id[i][j],x);
    		}
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=n+1;j++)
    		{
    			int x=read();
    			if(j==1)
    				add(id[i][j],s,x);
    			else if(j==n+1)
    				add(t,id[i][j-1],x);
    			else
    				add(id[i][j],id[i][j-1],x);
    		}
    	for(int i=s;i<=t;i++)
    		dis[i]=1e9;
    	priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q;
    	dis[s]=0;
    	q.push(make_pair(dis[s],s));
    	while(!q.empty())
    	{
    		int u=q.top().second;
    		q.pop();
    		if(v[u])
    			continue;
    		v[u]=1;
    		for(int i=h[u];i;i=e[i].ne)
    			if(dis[e[i].to]>dis[u]+e[i].va)
    			{
    				dis[e[i].to]=dis[u]+e[i].va;
    				q.push(make_pair(dis[e[i].to],e[i].to));
    			}
    	}
    	printf("%d
    ",dis[t]);
    	return 0;
    }
    
  • 相关阅读:
    设计模式之工厂模式-抽象工厂(02)
    1036 跟奥巴马一起编程 (15 分)
    1034 有理数四则运算 (20 分)
    1033 旧键盘打字 (20 分)
    1031 查验身份证 (15 分)
    大学排名定向爬虫
    1030 完美数列 (25 分)二分
    1029 旧键盘 (20 分)
    1028 人口普查 (20 分)
    1026 程序运行时间 (15 分)四舍五入
  • 原文地址:https://www.cnblogs.com/lokiii/p/10775475.html
Copyright © 2011-2022 走看看