LightOJ-1074 Extended Traffic

题目链接:https://vjudge.net/problem/LightOJ-1074

最短路问题,而且会有负环,需要把负环上的点都找出来,用spfa+dfs

用stack实现的spfa,比起用queue实现的快了有一倍(有负环情况下stack更快)

这题卡了很久,因为一个莫名的地方(代码里用注释标出来了),心累。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<stack>
using namespace std;
const int N=200+20;
const int inf=0x3f3f3f3f;
int g[N][N];
bool vis[N],r[N],g0[N][N];
int d[N],c[N];
int t,n,m,qu;
void dfs(int u) //寻找负环并标记 
{
	r[u]=true;
	for(int i=1;i<=n;i++)
	if(g0[u][i]&&!r[i])
	dfs(i);
}
int main()
{
	scanf("%d",&t);
	int kase=0;
	while(t--)
	{
		int num[N],cnt[N],a,b;
		memset(g,inf,sizeof(g));
		memset(g0,false,sizeof(g0));
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
		scanf("%d",&num[i]);
		scanf("%d",&m);
		for(int i=0;i<m;i++)
		{
			scanf("%d%d",&a,&b);
			g[a][b]=(num[b]-num[a])*(num[b]-num[a])*(num[b]-num[a]);
			g0[a][b]=true;
		}
		stack<int> q;
		q.push(1);
		memset(d,inf,sizeof(d));
		memset(vis,false,sizeof(vis));
		memset(r,false,sizeof(r));
		memset(cnt,0,sizeof(cnt));
		d[1]=0;vis[1]=true;cnt[1]=1;
		while(!q.empty())  //spfa 
		{
			int u=q.top();
			q.pop();vis[u]=false;
			for(int i=1;i<=n;i++)
			if(!r[i]&&g0[u][i]&&d[i]>d[u]+g[u][i]) //必须先判断g0[u][i]是否联通???不然WA!!! 
			{
				d[i]=d[u]+g[u][i];
				if(!vis[i])
				{
					q.push(i);
					vis[i]=true;
					cnt[i]++;
					if(cnt[i]>n)
					dfs(i);
				}
			}
		}
		scanf("%d",&qu);
		for(int i=0;i<qu;i++)
		scanf("%d",&c[i]);
		printf("Case %d:\n",++kase);
		for(int i=0;i<qu;i++)
		{
			a=c[i];
			if(d[a]<3||d[a]>=inf||r[a]) printf("?\n");
			else printf("%d\n",d[a]);
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值