很久以前还有过一篇floyd和dijkstra的东西虽然写得丑也放上来吧
floyd
多源最短路,k要放在外面。
for(k=1;k<=n;k++)
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]);
dijkstra
用优先队列维护,不能有负权边。
memset(dist,0x3f,sizeof(dist));
dist[1]=0; q.push(PLI(0,1)); //priority_queue
while(!q.empty())
{
int u=q.top().second;
LL di=q.top().first;
q.pop();
if(di>dist[u]) continue;
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i].first,w=G[u][i].second;
if(dist[v]>dist[u]+w)
{
dist[v]=dist[u]+w;
q.push(PLI(dist[v],v));
}
}
}
spfa
用队列存储可以松弛其他点的点,代码自行参考下面代码建完图之后的部分。
还可以用dfs来写,求负环会比较好。
void dfs(int u,double x)
{
vis[u]=true;
for(node *p=head[u];p!=NULL;p=p->nxt)
{
int v=p->v;
double w=p->w-x;
if(dist[v]>dist[u]+w)
{
if(vis[v]) { f=true; break; }
dist[v]=dist[u]+w;
dfs(v,x);
}
}
vis[u]=false;
}
差分约束
1.定义
如果一个系统由n个变量和m个约束条件组成,形成m个形如 的不等式( ,k为常数),则称其为差分约束系统(system of difference constraints)。亦即,差分约束系统是求解关于一组变量的特殊不等式组的方法。
###2.求解
求解差分约束系统,可以转化成图论的单源最短路径(或最长路径)问题。
观察不等式 ,可以成为 ,长得就像求最短路时的松弛操作。所以对于每个不等式,可以建一条从j到i的有向边,边权为k。
如果符号不是≤,那就转化啊。
可以转化为
;
可以转化为
;
可以转化为
(然后再继续转化一下即可)。
如果要求最大值,那么转化为≤,跑最短路;如果要求最小值,那么转化为≥,跑最长路。
跑最短路时,如果发现负环,就说明题目给的信息矛盾,不等式组无解;
如果到达不了,就说明有变量没有被约束。
以下是bzoj1731的代码(就当一个写得比较丑的板子):
#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
#include<algorithm>
#define maxn 1005
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
struct node { int v,w; };
int n,ml,md,dist[maxn],cnt[maxn];
bool inq[maxn];
vector<node> G[maxn];
queue<int> q;
int main()
{
scanf("%d%d%d",&n,&ml,&md);
for(int i=2;i<=n;i++)
{
node p;
p.v=i-1,p.w=0;
G[i].push_back(p);
}
for(int i=1;i<=ml;i++)
{
int u; node p;
scanf("%d%d%d",&u,&p.v,&p.w);
G[u].push_back(p);
}
for(int i=1;i<=md;i++)
{
int u; node p;
scanf("%d%d%d",&p.v,&u,&p.w);
p.w=-p.w;
G[u].push_back(p);
}
memset(dist,0x3f,sizeof(dist));
dist[1]=0,inq[1]=true,cnt[1]=1;
q.push(1);
while(!q.empty())
{
int u=q.front();q.pop();
inq[u]=false;
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i].v,d=G[u][i].w;
if(dist[v]>dist[u]+d)
{
dist[v]=dist[u]+d;
if(!inq[v])
{
cnt[v]++;
q.push(v);inq[v]=true;
if(cnt[v]>=n) { printf("-1\n"); return 0; }
}
}
}
}
printf("%d\n",dist[n]==INF?-2:dist[n]);
}
题目:bzoj1731