• luogu4001 [BJOI2006]狼抓兔子


    裸dinic就跑过去了,哪用得着平面图最小割=最短路……

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <queue>
    using namespace std;
    int n, m, w, ss, tt, hea[1000005], cnt, lev[1000005], cur[1000005], maxFlow;
    const int oo=0x3f3f3f3f;
    queue<int> d;
    struct Edge{
        int too, nxt, val;
    }edge[8000005];
    void add_edge(int fro, int too, int val){
        edge[cnt].nxt = hea[fro];
        edge[cnt].too = too;
        edge[cnt].val = val;
        hea[fro] = cnt++;
    }
    void addEdge(int fro, int too, int val){
        add_edge(fro, too, val);
        add_edge(too, fro, val);//无向边一开始就能增广
    }
    int f(int a, int b){
        return (a-1)*m+b;
    }
    bool bfs(){
        memset(lev, 0, sizeof(lev));
        lev[ss] = 1;
        d.push(ss);
        while(!d.empty()){
            int x=d.front();
            d.pop();
            for(int i=hea[x]; i!=-1; i=edge[i].nxt){
                int t=edge[i].too;
                if(!lev[t] && edge[i].val>0){
                    lev[t] = lev[x] + 1;
                    d.push(t);
                }
            }
        }
        return lev[tt]!=0;
    }
    int dfs(int x, int lim){
        if(x==tt)	return lim;
        int addFlow=0;
        for(int &i=cur[x]; i!=-1; i=edge[i].nxt){
            int t=edge[i].too;
            if(lev[t]==lev[x]+1 && edge[i].val>0){
                int tmp=dfs(t, min(lim-addFlow, edge[i].val));
                edge[i].val -= tmp;
                edge[i^1].val += tmp;
                addFlow += tmp;
                if(addFlow==lim)	break;
            }
        }
        return addFlow;
    }
    void dinic(){
        while(bfs()){
            for(int i=ss; i<=tt; i++)	cur[i] = hea[i];
            maxFlow += dfs(ss, oo);
        }
    }
    int main(){
        memset(hea, -1, sizeof(hea));
        cin>>n>>m;
        for(int i=1; i<=n; i++)
            for(int j=1; j<m; j++){
                scanf("%d", &w);
                addEdge(f(i,j), f(i,j+1), w);
            }
        for(int i=1; i<n; i++)
            for(int j=1; j<=m; j++){
                scanf("%d", &w);
                addEdge(f(i,j), f(i+1,j), w);
            }
        for(int i=1; i<n; i++)
            for(int j=1; j<m; j++){
                scanf("%d", &w);
                addEdge(f(i,j), f(i+1,j+1), w);
            }
        ss = f(1,1); tt = f(n,m);
        dinic();
        cout<<maxFlow<<endl;
        return 0;
    }
    

    平面图最短路:

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    int n, m, ss, tt, uu, hea[2000005], cnt, dis[2000005], din;
    bool vis[2000005];
    const int oo=0x3f3f3f3f;
    int p(int a, int b){
    	return (a-1)*(m-1)+b;
    }
    int q(int a, int b){
    	return p(a,b)+(n-1)*(m-1);
    }
    struct Edge{
    	int too, nxt, val;
    }edge[8000005];
    struct Node{
    	int idx, val;
    }nd[9000005];
    bool cmp(Node x, Node y){
    	return x.val>y.val;
    }
    void add_edge(int fro, int too, int val){
    	edge[++cnt].nxt = hea[fro];
    	edge[cnt].too = too;
    	edge[cnt].val = val;
    	hea[fro] = cnt;
    }
    void addEdge(int fro, int too, int val){
    	add_edge(fro, too, val);
    	add_edge(too, fro, val);
    }
    void dijk(){
    	memset(dis, 0x3f, sizeof(dis));
    	dis[ss] = 0;
    	nd[++din] = (Node){ss, 0};
    	while(din){
    		Node x=nd[1];
    		pop_heap(nd+1, nd+1+din, cmp);
    		din--;
    		if(vis[x.idx])	continue;
    		vis[x.idx] = true;
    		for(int i=hea[x.idx]; i; i=edge[i].nxt){
    			int t=edge[i].too;
    			if(!vis[t] && dis[t]>dis[x.idx]+edge[i].val){
    				dis[t] = dis[x.idx] + edge[i].val;
    				nd[++din] = (Node){t, dis[t]};
    				push_heap(nd+1, nd+1+din, cmp);
    			}
    		}
    	}
    }
    int main(){
    	cin>>n>>m;
    	if(n==1 || m==1){
    		int tmp=oo;
    		for(int i=1; i<=max(n,m); i++){
    			scanf("%d", &uu);
    			tmp = min(tmp, uu);
    		}
    		cout<<tmp<<endl;
    		return 0;
    	}
    	ss = 0; tt = q(n-1,m-1) + 1;
    	for(int i=1; i<=n; i++)
    		for(int j=1; j<m; j++){
    			scanf("%d", &uu);
    			if(i==1)	addEdge(ss, p(i,j), uu);
    			else if(i==n)	addEdge(q(i-1,j), tt, uu);
    			else	addEdge(q(i-1,j), p(i,j), uu);
    		}
    	for(int i=1; i<n; i++)
    		for(int j=1; j<=m; j++){
    			scanf("%d", &uu);
    			if(j==1)	addEdge(tt, q(i,j), uu);
    			else if(j==m)	addEdge(p(i,j-1), ss, uu);
    			else	addEdge(p(i,j-1), q(i,j), uu);
    		}
    	for(int i=1; i<n; i++)
    		for(int j=1; j<m; j++){
    			scanf("%d", &uu);
    			addEdge(p(i,j), q(i,j), uu);
    		}
    	dijk();
    	cout<<dis[tt]<<endl;
    	return 0;
    }
    
  • 相关阅读:
    PHP foreach 循环
    C#导出Excel时间格式问题
    vs2015 key
    C# 的Chart
    线程暂停与继续实现
    CCNA网络工程师学习进程(2)基本的网络设备
    CCNA网络工程师学习进程(1)网络的基本概述
    安卓学习进程(3)安卓开发工具的简介
    安卓学习进程(2)Android开发环境的搭建
    安卓学习进程(1)移动平台开发的简介
  • 原文地址:https://www.cnblogs.com/poorpool/p/8805379.html
Copyright © 2020-2023  润新知