• BZOJ 1001 狼抓兔子 (最大流转最短路) xgtao


    狼抓兔子

    1001: [BeiJing2006]狼抓兔子

    题目的意思是用最少的狼封闭所有道路(即切断起点和终点),典型的最小割模型。转化一下,就给你一个二分图,让你求最大流。点数多达1000000,边数6000000条,用普通的网络流是没法过的。

    那么把它转化为对偶图, 详见周东最大最小定理的论文,就这样建图。

    WA了一发后,发现一定要注意m==1 || n==1时的特判,因为对偶图满足的是欧拉定理,而当它是一条线的时候,是不满足的。

    #include <cstdio>
    #include <iostream>
    #include <queue>
    #include <algorithm>
    using namespace std;
    const int maxn = 2000020;
    const int maxm = 6000020;
    const int inf  = 1<<30;
    struct node{
    	int d,u;
    	bool operator < (const node &rhs)const{
    		return d > rhs.d;
    	}
    };
    
    struct edge{
    	int v,x;
    	edge *nxt;
    }*cur,*head[maxn],meo[maxm];
    int m,n,dis[maxn],done[maxn];
    
    void adde(int u,int v,int x){
    	cur->v = v;
    	cur->x = x;
    	cur->nxt = head[u];
    	head[u] = cur++;
    	
    	cur->v = u;
    	cur->x = x;
    	cur->nxt = head[v];
    	head[v] = cur++;
    }
    
    void read(int &x) {
        char c;
        while((c=getchar())<'0' || c>'9');
        x=c-'0';
        while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0';
    }
    
    void Dijkstra(int s){
    	priority_queue <node>q;
    	for(int i = 0;i <= m*n*2+2;++i)dis[i] = inf;
    	dis[s] = 0;
    	q.push((node){dis[s],s});
    	while(!q.empty()){
    		node p = q.top();q.pop();
    		int u = p.u;
    		if(done[u])continue;
    		done[u] = true;
    		for(edge *it = head[u];it;it = it->nxt){
    			int v = it->v;
    			if(dis[v] > dis[u]+it->x){
    				dis[v] = dis[u]+it->x;
    				q.push((node){dis[v],v});
    			}
    		}
    	}
    }
    
    int address(int x,int y){
    	return ((x-1)*(m-1)+y)*2-1;
    }
    
    int main(){
    	cur = meo;
    	scanf("%d%d",&n,&m);
    	const int S = 0;
    	const int T = 2*n*m+2;
    	int x,ans = inf;
    	if (n == 1 || m == 1)  {  
            if (n > m) swap(n, m);
            int ans = inf;  
            for (int i = 1; i < m; ++i){  
                read(x);
                ans = min(ans,x);
            }  
            printf("%d\n",ans);  
            exit(0);
        }  
    	for(int i = 1;i <= n;++i){
    		for(int j = 1;j < m;++j){
    			read(x);
    			if(i == 1){
    				adde(address(i,j),S,x);
    			}
    			else if(i == n){
    				adde(address(i-1,j)+1,T,x);
    			}
    			else{
    				adde(address(i-1,j)+1,address(i,j),x);
    			}
    		}
    	}
    	for(int i = 1;i < n;++i){
    		for(int j = 1;j <= m;++j){
    			read(x);
    			if(j == 1){
    				adde(address(i,j)+1,T,x);
    			}
    			else if(j == m){
    				adde(address(i,j-1),S,x);
    			}
    			else{
    				adde(address(i,j-1),address(i,j)+1,x);
    			}
    		}
    	}
    	for(int i = 1;i < n;++i){
    		for(int j = 1;j < m;++j){
    			read(x);
    			int pos = address(i,j),pos2 = address(i,j)+1;
    			adde(address(i,j),address(i,j)+1,x);
    		}
    	}
    	Dijkstra(S);
    	printf("%d\n",dis[T]);
    	return 0;
    }
    

      

  • 相关阅读:
    DataTable四个方法
    c++面向对象编程必备“良方”(转)
    函数调用约定
    AFX_IDW_PANE_FIRST(转)
    CString.Format的详细用法(转)
    ID的分配 (转)
    CString用法整理(转载)
    jquery之效果
    JS 水仙数
    CSS 文本换行
  • 原文地址:https://www.cnblogs.com/xgtao984/p/5697795.html
Copyright © 2020-2023  润新知