BZOJ 1001 狼抓兔子 平面图的最小割

题目链接:

https://www.lydsy.com/JudgeOnline/problem.php?id=1001

题目大意:

见链接

思路:

求最小割,平面图的最小割等价于对偶图的最短路

直接建图求最短路即可,只是图比较难建。

  1 #include<bits/stdc++.h>
  2 #define IOS ios::sync_with_stdio(false);//不可再使用scanf printf
  3 #define Max(a, b) ((a) > (b) ? (a) : (b))//禁用于函数,会超时
  4 #define Min(a, b) ((a) < (b) ? (a) : (b))
  5 #define Mem(a) memset(a, 0, sizeof(a))
  6 #define Dis(x, y, x1, y1) ((x - x1) * (x - x1) + (y - y1) * (y - y1))
  7 #define MID(l, r) ((l) + ((r) - (l)) / 2)
  8 #define lson ((o)<<1)
  9 #define rson ((o)<<1|1)
 10 #pragma comment(linker, "/STACK:102400000,102400000")//栈外挂
 11 using namespace std;
 12 inline int read()
 13 {
 14     int x=0,f=1;char ch=getchar();
 15     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
 16     while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
 17     return x*f;
 18 }
 19 
 20 typedef long long ll;
 21 const int maxn = 6000000 + 10;
 22 const int mod = 1000000007;//const引用更快,宏定义也更快
 23 const int INF = 1e9;
 24 
 25 struct edge
 26 {
 27     int next;//指向下一个节点
 28     int u, v, w;
 29 };
 30 edge a[maxn];
 31 int head[maxn], node;//node记录节点的数目,head[i]记录连接着i的第一条边
 32 void addedge(int u, int v, int w)
 33 {
 34     a[node].u = u;
 35     a[node].v = v;
 36     a[node].w = w;
 37     a[node].next = head[u];
 38     head[u] = node++;
 39     a[node].u = v;
 40     a[node].v = u;
 41     a[node].w = w;
 42     a[node].next = head[v];
 43     head[v] = node++;
 44 }
 45 struct Heapnode
 46 {
 47     int d, u;//d为距离,u为起点
 48     Heapnode(){}
 49     Heapnode(int d, int u):d(d), u(u){}
 50     bool operator <(const Heapnode & a)const
 51     {
 52         return d > a.d;//这样优先队列先取出d小的
 53     }
 54 };
 55 ll n, m;
 56 bool v[maxn];//标记点是否加入集合
 57 int d[maxn];//起点s到各个点的最短路
 58 void init(int n)
 59 {
 60     node = 0;
 61     memset(head, -1, sizeof(head));
 62 }
 63 priority_queue<Heapnode>q;
 64 void dijkstra(ll s, ll n)//以s为起点
 65 {
 66     while(!q.empty())q.pop();
 67     for(int i = 0; i <= n; i++)d[i] = INF;
 68     d[s] = 0;
 69     memset(v, 0, sizeof(v));
 70     q.push(Heapnode(0, s));
 71     while(!q.empty())
 72     {
 73         Heapnode now = q.top();
 74         q.pop();
 75         ll u = now.u;//当前起点
 76         if(v[u])continue;//如果已经加入集合,continue
 77         v[u] = 1;
 78         for(int i = head[u]; i != -1; i = a[i].next)
 79         {
 80             edge& e = a[i];//引用节省代码
 81             if(d[e.v] > d[u] + e.w)
 82             {
 83                 d[e.v] = d[u] + e.w;
 84                 q.push(Heapnode(d[e.v], e.v));
 85             }
 86         }
 87     }
 88 }
 89 
 90 int main()
 91 {
 92     ll n, m;
 93     while(scanf("%lld%lld", &n, &m) != EOF)
 94     {
 95         if(n == 1 || m == 1)
 96         {
 97             ll ans = INF, x;
 98             for(int i = 1; i < max(n, m); i++)
 99                 scanf("%lld", &x), ans = min(ans, x);
100             printf("%lld\n", ans);
101             continue;
102         }
103         ll x;
104         ll t = 0, s = (n - 1) * (m - 1) * 2 + 1;
105         init(s);
106         ll tmp = (m - 1) * 2;//每一行的数目
107         for(int i = 1; i <= n; i++)
108             for(int j = 1; j < m; j++)
109             {
110                 scanf("%lld", &x);
111                 if(i == 1)addedge(j * 2, t, x);
112                 else if(i == n)addedge(s, (n - 2) * tmp + 2 * j - 1, x);
113                 else addedge((i - 1) * tmp + 2 * j, (i - 2) * tmp + 2 * j - 1, x);
114             }
115         for(int i = 1; i < n; i++)
116             for(int j = 1; j <= m; j++)
117             {
118                 scanf("%lld", &x);
119                 if(j == 1)addedge(s, (i - 1) * tmp + 1, x);
120                 else if(j == m)addedge(i * tmp, t, x);
121                 else addedge((i - 1) * tmp + 2 * j - 2, (i - 1) * tmp + 2 * j - 1, x);
122             }
123         for(int i = 1; i < n; i++)
124             for(int j = 1; j < m; j++)
125             {
126                 scanf("%lld", &x);
127                 addedge((i - 1) * tmp + 2 * j - 1, (i - 1) * tmp + 2 * j, x);
128             }
129         dijkstra(s, s);
130         printf("%d\n", d[t]);
131     }
132     return 0;
133 }

 

posted @ 2018-09-10 23:05  _努力努力再努力x  阅读(132)  评论(0编辑  收藏  举报