pku3169 差分约束系统

Layout

这题还是用的 SPFA + 栈 过的,400多ms,写得多了,发现都可以套用模块了,除了输入不太一样外,其他的都基本一样。

模块一:负责各个数组的初始化

模块二:负责加边,对边用邻接表处理

模块三:SPFA 用栈来实现的过程

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
#include < stdio.h >
#include
< stdlib.h >
#define INF 0xfffffff
#define NN 1004
#define MM 20004

int edNum, N;
int next[MM];
int root[NN];
int mark[NN];
int cnt[NN];
int dis[NN];
int stack[NN];

struct node{
int e, v;
}edge[MM];

/* 在这里我用了一个函数来完成初始化,也可以看着一个固定模块了 */
/* 模块一 */
void Init(){
int i;
for (i = 0 ; i <= N; i ++ ){
root[i]
= - 1 ;
mark[i]
= 0 ;
cnt[i]
= 0 ;
}
}
/* 模块二 */
void add( int a, int b, int c){
edge[edNum].e
= b;
edge[edNum].v
= c;
next[edNum]
= root[a];
root[a]
= edNum ++ ;
}
/* 函数返回-1,表示有负边权回路,就表示不可能
函数返回-2,就表示起点到终点的距离不定,这里用dis[N] == INF,来判断,因为开始就是赋值的是INF
否者,返回dis[N],这里面存的就是起点到终点的最大距离
*/
/* 模块三 */
int Spfa()
{
int i, top, cur, tmp, nxt;
top
= 0 ;
for (i = 1 ; i <= N; i ++ ){
dis[i]
= INF;
if (root[i] != - 1 ){
stack[
++ top] = i;
cnt[i]
++ ;
mark[i]
= 1 ;
}
}
dis[
1 ] = 0 ;

while (top){
cur
= stack[top -- ];
tmp
= root[cur];
mark[cur]
= 0 ;
while (tmp != - 1 ){
nxt
= edge[tmp].e;
if (dis[nxt] > dis[cur] + edge[tmp].v){
dis[nxt]
= dis[cur] + edge[tmp].v;
if ( ! mark[nxt]){
cnt[nxt]
++ ;
if (cnt[nxt] > N + 1 ){
return - 1 ;
}
mark[nxt]
= 1 ;
stack[
++ top] = nxt;
}
}
tmp
= next[tmp];
}
}
if (dis[N] == INF){
return - 2 ;
}
return dis[N];
}
int main()
{
int ML, MD, a, b, c;
scanf(
" %d%d%d " , & N, & ML, & MD);
Init();
while (ML -- ){
scanf(
" %d%d%d " , & a, & b, & c);
add(a, b, c);
}
while (MD -- ){
scanf(
" %d%d%d " , & a, & b, & c);
add(b, a,
- c);
}
printf(
" %d\n " , Spfa());
// system("pause");
return 0 ;
}

 

转载于:https://www.cnblogs.com/ylfdrib/archive/2010/07/22/1782948.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值