您的位置:首页 > 其它

poj 2983 Is the Information Reliable? 差分约束判断回路

2011-01-26 21:08 351 查看
这题加深我对差分约束的源点理解。

这题是判断图中是否存在环(用最短路或最长路), 开始用spfa, 狂WA,想不通,看了讨论说要添加一个超源点,添加了就AC了。

总结:用spfa算法判断图中是否存在环,要保证从源点开始,能到达各个顶点,这样才能保证差分约束里的各个不等式成立。因为要是源点到达不了某个顶点的话(即图是不连通的),那么从该顶点就无法入队,导致从该顶点出发的所有不等式,都没有得到检查。

而是使用bellman_ford算法,则不用添加超源点,因为它对图中每一条边都为做n-1次松弛,就保证每个顶点都得到更新。

#include <iostream>
#include <queue>
using namespace std;

const int MAX = 500000;
const int INF = 1000000000;
const int N = 2000;

struct Node
{
int v;
int cost;
int next;
};

Node node[MAX];
int cnt
;
int adj
;
bool in_q
;
int d
;
int size;
int n, m;

void add_edge(int u, int v, int cost)
{
node[size].v = v;
node[size].cost = cost;
node[size].next = adj[u];
adj[u] = size++;
}

bool spfa()
{
queue<int> Q;

memset(cnt, 0, sizeof(cnt));
memset(in_q, false, sizeof(in_q));
for (int i = 0; i <= n; i++)
d[i] = -INF;

int u,v,w;
//从超源点开始搜索
d[0] = 0;
in_q[0] = true;
Q.push(0);

while (!Q.empty())
{
u = Q.front();
Q.pop();
in_q[u] = false;

for (int i = adj[u]; i != -1; i = node[i].next)
{
v = node[i].v;
w = node[i].cost;

if (d[v] < d[u]+w)
{
d[v] = d[u] + w;
if (!in_q[v])
{
in_q[v] = true;
Q.push(v);

if (++cnt[v] >= n) return false;
}
}
}
}

return true;
}

bool bellman_ford()
{
for (int i = 0; i <= n; i++)
d[i] = -INF;

bool isfinish;
for (int i = 1; i <= n; i++)
{
isfinish = true;
for (int u = 0; u <= n; u++)
for (int k = adj[u]; k != -1; k = node[k].next)
if (d[node[k].v] < d[u] + node[k].cost)
{
d[node[k].v] = d[u] + node[k].cost;
isfinish = false;
}

if (isfinish) break;

}

for (int u = 0; u <= n; u++)
for (int k = adj[u]; k != -1; k = node[k].next)
if (d[node[k].v] < d[u] + node[k].cost)
return false;

return true;
}

int main()
{
char c;
int a, b ,w;

while (scanf("%d%d", &n, &m) != EOF)
{
size = 0;
for (int i = 0; i <= n; i++)
adj[i] = -1;

for (int i = 0; i < m; i++)
{
getchar();
scanf("%c", &c);
if (c == 'P')
{
scanf("%d%d%d", &a, &b, &w);
add_edge(b, a, w);
add_edge(a, b, -w);
}
else if (c == 'V')
{
scanf("%d%d", &a, &b);
add_edge(b, a, 1);
}
}

//使用bellman就不需要添加超源点
//添加超源点到所有点的边
//for (int i = 1; i <= n; i++)
//	add_edge(0, i, 0);

if (bellman_ford())
printf("Reliable\n");
else
printf("Unreliable\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: