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 }
越努力,越幸运