bzoj 1001
来源:互联网 发布:mysql联表删除 编辑:程序博客网 时间:2024/05/20 06:31
#include<iostream>#include<cstdio>#include<algorithm>#include<functional>#include<queue>using namespace std;typedef pair<int, int>p;struct edgee{ int to; int value;}edge[6000020];int num[1020][1020][2],edgetot,first[2000020],nextt[6000020];void addedge(int a, int b,int value){ edge[edgetot].to = b; edge[edgetot].value = value; nextt[edgetot] = first[a]; first[a] = edgetot; edgetot++; edge[edgetot].to = a; edge[edgetot].value = value; nextt[edgetot] = first[b]; first[b] = edgetot; edgetot++;}struct com{ bool operator()(p a, p b) { if (a.first == b.first) return false; return a.first >b.first; }};priority_queue < p, vector<p>, com > que;int d[2000020],m,n;int distra(int s){ d[0] = 0; d[2 * (n - 1)*(m - 1)+1] = 1000000000; for (int i = 1; i <n;i++) for (int j = 1; j < m;j++) for (int k = 0; k < 2; k++) { d[num[i][j][k]] = 1000000000; } que.push(p(0, 0)); while (!que.empty()) { p c = que.top(); que.pop(); if (c.first > d[c.second]) continue; for (int i = first[c.second]; i != -1; i = nextt[i]) { int to = edge[i].to; if (d[to]>d[c.second] + edge[i].value) { d[to] = d[c.second] + edge[i].value; que.push(p(d[to], to)); } } } return d[2 * (n - 1)*(m - 1)+1];//在这就返回终点值}int diantot=1;int main(){ scanf("%d%d", &n, &m); if (n == 1 || m == 1)//这是特判条件 { int a, j=1000000000; if (n < m)swap(n, m); for (int i = 1; i < n; i++) { scanf("%d", &a); if (a < j)j = a; } if (j != 1000000000) printf("%d\n", j); else printf("0\n"); exit(0); } for (int j = 0; j <= m; j++)//预先给每个点一个编号,虽然这样会搞得常数很大不过好算啊。。。。能过就行。 { //第i行j列的格子包含2个子节点 右上的是num[i][j][0],左下的是num[i][j][1]; num[0][j][0]=num[0][j][1] = 0; num[n][j][0] = num[n][j][1] = 2 * (n - 1)*(m - 1) + 1; } for (int i = 1; i < n;i++) for (int j = 1; j < m; j++) { num[i][j][0] = diantot++; num[i][j][1] = diantot++; } for (int i = 0; i <= 2 * (n - 1)*(m - 1) + 1; i++)//记得初始化头结点在遍历边的时候等于-1就停止了,如果边有1 2 3 4 那么加边时就是 -1 加1边 1 -1 加2边 2 1 -1 加3边 3 2 1 -1.。。 { first[i] = -1; } for (int i = 1; i <= n; i++)//建横向边 for (int j = 1; j < m; j++) { int a; scanf("%d", &a); addedge(num[i][j][0], num[i - 1][j][1], a); }//纵向边 for (int i = 1; i < n; i++) { int a1; scanf("%d", &a1); addedge(num[i][1][1], 2 * (n - 1)*(m - 1) + 1, a1); for (int j = 2; j < m; j++) { int a2; scanf("%d", &a2); addedge(num[i][j][1], num[i][j-1][0], a2); } int a3; scanf("%d", &a3); addedge(num[i][m - 1][0], 0, a3); }//斜的边 for (int i = 1; i < n;i++) for (int j = 1; j < m; j++) { int a3; scanf("%d", &a3); addedge(num[i][j][0], num[i][j][1], a3); }//一下是调试代码。。调试技巧://1. 看图建没建好你阔以让每条边的值不同这样输出时就会知道边在哪里了 2.注意使用pair时 分清first 与second 的意义3.最后一个点事2*(n-1)*(m-1)+1不是2*(n-1)*(m-1) /*for (int i = 1; i < n;i++) for (int j = 1; j < m; j++) { cout << "i:" << i << " " << "j:" << j << " " << "num0:" << num[i][j][0] << endl; cout << "i:" << i << " " << "j:" << j << " " << "num1:" << num[i][j][1] << endl; } for (int i = 0; i < 2 * (n - 1)*(m - 1) + 2; i++) { cout << "begin: " << i << " "; for (int j = first[i]; j != -1; j = nextt[j]) { cout << "边value:"<<edge[j].value<<" "<<"边to:"<<edge[j].to << " "; } cout << endl; }*/ printf("%d\n",distra(0));}
此题就是一个最短路。。每次都是从外面到外面的切割发现所以就是相当于不管条件怎么变起点和终点都不会变那么我们阔以考虑最短路(当然只是考虑用,能不能用看情况,这题刚好阔以)。。。
这是个讲的不错的大神。。如有疑问可参考一下
http://blog.csdn.net/nikelong0/article/details/50727840
0 0
- Bzoj-1001
- bzoj 1001
- Bzoj 1001
- BZOJ 1001
- bzoj 1001
- bzoj 1001
- BZOJ 1001 & SPFA
- bzoj 1001 最小割
- BZOJ-1001 (网络流)
- [BZOJ ]
- BZOJ****-****
- BZOJ
- BZOJ
- BZOJ
- BZOJ
- BZOJ
- BZOJ
- BZOJ
- 在网页中利用javascript实现动态时间的设计
- 【AtCoder Grand 013E】Placing Squares 题解
- Linux关机命令:halt shutdown reboot init
- 向死而生
- CSU 1870 Legendary
- bzoj 1001
- 机器学习(周志华)_第五章神经网络
- ArcGIS加载高德、OSM和谷歌等地图
- swift 泛型
- 在虚拟机上的kali使用无线网卡上网
- CEPH Ubuntu14.04 集群部署
- lua闭包
- 云化多租户架构
- new Integer()和Integer.valueOf()效率比较