您的位置:首页 > 其它

poj 2983 差分约束学习(用队列超时了,不防用栈试试)

2014-02-14 10:07 363 查看
对于差分约束,写了两道题,有了自己的想法,归纳为3点

1,找出所有条件,其中包括隐含的。

2,对所有条件进行分析,转化为3角不等式。

3,应用最短路,或最长路,进行松弛操作,或判环

差分约束题目有两种,一种求最大值,另外一种求最小值。

(1)当题目是求满足给定不等式的最小值时,就是求图的最长路。

建图方式如下:a – b >= c,对应于边b –> a w(b, a) = c, 然后求最短路;判断条件是:d[v] <= d[u] + w(u, v), 初始化d[]为-INF. 这样求出的d[]就是满足条件的最小值。原因很简单,因为d[i] 是从-INF开始增大,根据不等式逐渐增大,当满足所有不等式时,那么d[i]肯定是最小的了。

(2)当题目是求满足给定不等式的最大值时,就是求图的最短路。

建图方式如下:a – b <= c,对应于边b –> a w(b, a) = c, 然后求最长路;判断条件是:d[v] >= d[u] + w(u, v), 初始化d[]为INF.这样求出的d[]就是最大值。原因和上面一样,因为是从INF逐渐减小的,当满足完所有条件时,就停止。那么d[i]是最大的了。

推荐:spfa算法

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int M =  100008;
int top = 0;
struct {
int head;
}H[M];
struct {
int u,v,w,next;
}E[M*10];
void add(int u,int v,int w)
{
E[top].v = v;
E[top].w = w;
E[top].next = H[u].head;
H[u].head = top++;
}
void init()
{
top = 0;
memset(H,-1,sizeof(H));
memset(E,-1,sizeof(E));
}
bool spfa(int f,int n)
{
int d[M],vis[M],_cnt[M];
memset(d,63,sizeof(d));
d[f] = 0;
memset(vis,0,sizeof(vis));
memset(_cnt,0,sizeof(_cnt));
queue <int > q ;
q.push(f);
vis[f] = 1;
_cnt[f]++;
while(!q.empty())
{
int u = q.front();q.pop(),vis[u] = 0;
for(int i = H[u].head;i!=-1;i = E[i].next)
{

if(d[E[i].v]>d[u]+E[i].w)
{
d[E[i].v] = d[u] + E[i].w;
if(!vis[E[i].v])
{
q.push(E[i].v);
vis[E[i].v] = 1;
_cnt[E[i].v] ++;
if(_cnt[E[i].v]>n)return false;
}
}
}
}
return true;
}
int main()
{
int m,n;
while(~scanf("%d%d",&n,&m))
{
init();
char a[10];
int u,v,w;
while(m--)
{
scanf("%s",a);
if(a[0]=='P')
{
scanf("%d%d%d",&u,&v,&w);
add(u,v,-w);
add(v,u,w);
}
else
{
scanf("%d%d",&u,&v);
add(u,v,-1);
}
}
for(int i=1;i<=n;i++)add(0,i,0);
spfa(0,n)==true?puts("Reliable"):puts("Unreliable");

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: