bzoj 1001: [BeiJing2006]狼抓兔子 对偶图最短路-(最小割)

来源:互联网 发布:skyline软件 编辑:程序博客网 时间:2024/05/22 06:23

2333  开始做 大视野了,爽的不行

这是第二题

一看,不会,再看还是不会

后来知道是最小割问题,这里不适合, O n^2 m 的复杂度明显不行

后来又知道这是: 对偶图跑最短路 = 最小割

然后分析这个图,图中本来的带权边肯定要保留,然后就发现要用 一个小的面作为结点,

图外面的整个面要分为左下和右上两部分,同样这两部分要作为最短路的起点和终点

--------------------------------------------------------

关于  对偶图最短路 = 最小割 :

跑 dicnic的时候是找到每条通路,每次剪掉最小权边,而在对偶图中,跑完恰好是一条割断 原图起点终点连线的 最短路

通俗理解就是,如果不是连通的最短路,就起不到割断的作用


/**************************************************************    Problem: 1001    User: xiang_6    Language: C++    Result: Accepted    Time:2256 ms    Memory:95052 kb****************************************************************/ #include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <string>#include <cmath>#include <set>#include <map>#include <stack>#include <queue>#include <ctype.h>#include <vector>#include <algorithm>#include <sstream>#define PI acos(-1.0)#define in freopen("in.txt", "r", stdin)#define out freopen("out.txt", "w", stdout)using namespace std;typedef long long ll;const int maxn = 2000000 + 7, INF = 0x3f3f3f3f, mod = 1e9 + 7;const int M = maxn * 3 + 700;int n, m;int u, v; struct edge {    int v, cost;    int next;} edge[M];int head[maxn], ednum; struct node {    int v, w;    bool operator < (const node b)const {        return w > b.w;    }} cur, tail; void add(int u, int v, int cost) {    edge[ednum].v = v; edge[ednum].cost = cost;    edge[ednum].next = head[u]; head[u] = ednum++;     edge[ednum].v = u; edge[ednum].cost = cost;    edge[ednum].next = head[v]; head[v] = ednum++;} int d[maxn], vis[maxn];void dijkstra(int u, int v) {    for(int i = 0; i <= v; ++i) d[i] = INF;    memset(vis, 0, sizeof vis);    d[u] = 0;    priority_queue<node > qu;    cur.v = u; cur.w = 0;    qu.push(cur);    while(!qu.empty()) {        cur = qu.top(); qu.pop();        int x = cur.v;        if(vis[x]) continue;        vis[x] = 1;        for(int i = head[x]; i != -1; i = edge[i].next) {            if(d[edge[i].v] > edge[i].cost + d[x]) {                d[edge[i].v] = edge[i].cost + d[x];                tail.v = edge[i].v;                tail.w = d[edge[i].v];                qu.push(tail);            }        }    }    printf("%d\n", d[v]);}  void init() {    int x, y, cost;    for(int i = 1; i <= n; ++i) {        for(int j = 1; j < m; ++j) {            scanf("%d", &cost);            x = (i == 1 ? u : (2*(i-1)-1)*(m-1)+j);            y = (i == n ? v : 2*(i-1)*(m-1) + j);            add(x, y, cost);        }    }     for(int i = 1; i < n; ++i) {        for(int j = 1; j <= m; ++j) {            scanf("%d", &cost);            x = (j == 1 ? v : 2*(i-1)*(m-1)+j-1);            y = (j == m ? u : 2*(i-1)*(m-1)+j-1+m);            add(x, y, cost);        }    }     for(int i = 1; i < n; ++i) {        for(int j = 1; j < m; ++j) {            scanf("%d", &cost);            x = (2*(i-1)*(m-1)+j);            y = ((2*(i-1)+1)*(m-1)+j);            add(x, y, cost);        }    }} int main() {    while(scanf("%d %d", &n, &m) != EOF) {        memset(head, -1, sizeof head);        ednum = 0;                  // 结点个数        u = 0;                      // 起点        v = 2*(n-1)*(m-1)+1;        // 终点         init();        dijkstra(u, v);    }    return 0;} /*3 45 6 44 3 17 5 35 6 7 88 7 6 55 5 56 6 6*/



阅读全文
1 0