您的位置:首页 > 其它

Light oj 1074 - Extended Traffic SPFA+负权环判断

2016-07-17 14:25 351 查看
一道难度很一般的题。。

但是数组开小了,我的天,还是对SPFA理解不够深。!

一开始就RE但是我没注意到是数组开小的问题,哎,又花了好长时间细节上。

加油吧!

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;

const int inf = 0x3f3f3f3f;
int dict[2005],n,m,Left[20005],value[20005],Right[20005],nexts[20005],cnt,cc[20005];//这里left,right,value等数组一定不能小于边的数量!而不是点的,因为它存是按照边存的。
bool vis[2005],re[2005];

void init() {//初始化
cnt = 0;
memset(Left,-1,sizeof(Left));
memset(vis,false,sizeof(vis));
memset(cc,0,sizeof(cc));
memset(re,false,sizeof(re));
}

void add(int u,int v,int va) {
value[cnt] = va;
nexts[cnt] = Left[u];
Left[u] = cnt;
Right[cnt] = v;
cnt++;
}

int SPFA() {
for(int i = 1;i <= n;i++)
dict[i] = inf;
queue<int> q;
while(!q.empty()) q.pop();
dict[1] = 0;
vis[1] = true;
q.push(1);
cc[1]++;
while(!q.empty()) {
int temp = q.front();
q.pop();
if(cc[temp] > n+1) {//入队次数大于N就跳过
vis[temp] = true;
continue;
}
vis[temp] = false;
for(int i = Left[temp];i != -1;i = nexts[i]) {
if(re[Right[i]])
continue;
if(dict[Right[i]] > dict[temp] + value[i]) {
dict[Right[i]] = dict[temp] + value[i];
if(!vis[Right[i]]) {
q.push(Right[i]);
vis[Right[i]] = true;//每次入队检查该点入队次数,如果大于n说明存在负权环。
cc[Right[i]]++;
}
}
}
}
}

int main() {
int T,q,xx;
scanf("%d",&T);
for(int l = 1;l <= T;l++) {
scanf("%d",&n);
int num[205];
for(int i = 1;i <= n;i++) {
scanf("%d",&num[i]);
}
init();
scanf("%d",&m);
for(int i = 1;i <= m;i++) {
int x,y;
scanf("%d%d",&x,&y);
int tt = num[y] - num[x];
add(x,y,tt*tt*tt);
}
SPFA();
printf("Case %d:\n",l);
scanf("%d",&q);
for(int j = 1;j <= q;j++) {
scanf("%d",&xx);
if(dict[xx] < 3 || dict[xx] == inf || re[xx]) {
//printf("%d\n",dict[xx]);
printf("?\n");
}
else
printf("%d\n",dict[xx]);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息