UVA 515 King
2013-09-03 15:36
162 查看
差分约束系统的第一个题目,看了落花大神的博客后,对差分约束有了一定了解,关键在于建图,然后就是判断是否存在负权回路。
关于差分约束系统的解释详见维基百科:http://zh.wikipedia.org/wiki/%E5%B7%AE%E5%88%86%E7%BA%A6%E6%9D%9F%E7%B3%BB%E7%BB%9F
利用spfa判断时,当图中有顶点出队次数多于图中顶点数目时说明存在负环。
其实我自己敲上去的时候改了一点点。
大神的time[g[x][i].v]当达到n+1时就返回false,这是不对的,因为点包括0嘛,所以最终应该有n+1个点,判断就应该改为达到n+2,而且这一点也从uva上得到证明,
直接交n+1的版本是过不了的,n+2,才能过。
以下是我改过大神的代码:
然后我利用bellman—ford重新写了一遍,速度慢了将近一半,不知道是不是我写的姿势不对。
来自维基百科的bellman-ford的伪代码:
其实就是普通bellman-ford做完之后,再检查所有的边一次,看看能不能继续松弛,如果可以的话,松弛变数会超过:|V|-1,说明必须存在负权环。
关于差分约束系统的解释详见维基百科:http://zh.wikipedia.org/wiki/%E5%B7%AE%E5%88%86%E7%BA%A6%E6%9D%9F%E7%B3%BB%E7%BB%9F
利用spfa判断时,当图中有顶点出队次数多于图中顶点数目时说明存在负环。
其实我自己敲上去的时候改了一点点。
大神的time[g[x][i].v]当达到n+1时就返回false,这是不对的,因为点包括0嘛,所以最终应该有n+1个点,判断就应该改为达到n+2,而且这一点也从uva上得到证明,
直接交n+1的版本是过不了的,n+2,才能过。
以下是我改过大神的代码:
#include <cstdio> #include <cstring> #include <queue> #include <cstdlib> #include <vector> #define N 110 using namespace std; struct edgeType{ int v, w; edgeType(int a, int b):v(a), w(b){} }; int n, m, d , time , inq ; char op[10]; vector<edgeType> g ; bool spfa(void) { queue<int> q; time = 1; inq = 1; q.push(n); while(!q.empty()) { int x = q.front(); q.pop(); inq[x] = 0; for(int i = 0; i < g[x].size(); i++) if(d[g[x][i].v] > d[x] + g[x][i].w) { d[g[x][i].v] = d[x] + g[x][i].w; time[g[x][i].v]++; if(time[g[x][i].v] == n+2) return false; if(!inq[g[x][i].v]) { q.push(g[x][i].v); inq[g[x][i].v] = 1; } } } return true; } int main(void) { int a, b, c; while(scanf("%d%d",&n, &m)&&n) { n++; memset(d, 0x0f, sizeof(d)); memset(inq, 0, sizeof(inq)); memset(time, 0, sizeof(time)); d = 0; g .clear(); for(int i = 0; i < n;i++) g .push_back(edgeType(i, 0)), g[i].clear(); for(int i = 0; i < m; i++) { scanf("%d%d%s%d", &a, &b, op, &c); if(op[0] == 'g') g[a + b].push_back(edgeType(a - 1, -c - 1)); else g[a - 1].push_back(edgeType(a + b, c - 1)); } if(spfa()) puts("lamentable kingdom"); else puts("successful conspiracy"); } return 0; }
然后我利用bellman—ford重新写了一遍,速度慢了将近一半,不知道是不是我写的姿势不对。
来自维基百科的bellman-ford的伪代码:
# initialization for each v in V do d[v] ← ∞; d[source] ← 0 # Relaxation for i =1,...,|V|-1 do for each edge (u,v) in E do d[v] ← min{d[v], d[u]+w(u,v)} # Negative cycle checking for each edge (u, v) in E do if d[v]> d[u] + w(u,v) then no solution
其实就是普通bellman-ford做完之后,再检查所有的边一次,看看能不能继续松弛,如果可以的话,松弛变数会超过:|V|-1,说明必须存在负权环。
#include <cstdio> #include <cstring> #include <queue> #include <cstdlib> #include <vector> #define N 110 using namespace std; struct edgeType { int v, w; edgeType(int a, int b):v(a), w(b) {} }; int n, m, d , inq ; char op[10]; vector<edgeType> g ; bool bellman_ford(void) { for(int k = 0; k < n; k++) for(int x = 0; x <= n; x++) for(int i = 0; i < (int)g[x].size(); i++) if(d[g[x][i].v] > d[x] + g[x][i].w) d[g[x][i].v] = d[x] + g[x][i].w; for(int i = 0; i <= n; i++) { for(int k = 0; k < (int)g[i].size(); k++) if(d[g[i][k].v] > d[i] + g[i][k].w) return false; } return true; } int main(void) { int a, b, c; while(scanf("%d",&n)&&n) { n++; scanf("%d", &m); memset(d, 0x0f, sizeof(d)); memset(inq, 0, sizeof(inq)); d = 0; g .clear(); for(int i = 0; i < n; i++) g .push_back(edgeType(i, 0)), g[i].clear(); for(int i = 0; i < m; i++) { scanf("%d%d%s%d", &a, &b, op, &c); if(op[0] == 'g') g[a + b].push_back(edgeType(a - 1, -c - 1)); else g[a - 1].push_back(edgeType(a + b, c - 1)); } if(bellman_ford()) puts("lamentable kingdom"); else puts("successful conspiracy"); } return 0; }
相关文章推荐
- UVA 515 - King (SPFA)
- King - UVa 515 差分约束系统
- uva 515 - King(差分约时系统)
- UVa 515 - King
- UVa 515 - King (差分约束系统 + SPFA求带负权最短路)
- POJ 1364 King (UVA 515) 差分约束
- UVA 515 King
- uva 515 King
- POJ 1364 King (UVA 515) 差分约束
- UVA 515 King
- uva 515 King(差分约束)
- UVa 515 King (差分约束+线性规划+判负圈)
- UVA 515 King
- UVA 515 King
- UVA 515 - King 差分约束系统
- UVA 515 - King 差分约束系统
- UVa 515 King (差分约束系统)
- UVA515 King
- UVA 515 - King(差分约束系统)
- UVa 515 King(差分约束系统)