【NOIP2014 Day2 T2】寻找道路

【NOIP2014 Day2 T2】寻找道路

Time Limit:10000MS  Memory Limit:131072K
Total Submit:33 Accepted:25 
Case Time Limit:1000MS

Description

 

Input

 

Output

 

Sample Input

样例输入1:
3 2
1 2
2 1
1 3

样例输入2:
6 6
1 2
1 3
2 6
2 5
4 5
3 4
1 5

Sample Output

样例输出1:
-1

样例输出2:
3

Hint

 
 
 

Source

感谢nodgd放上题目



最短路的反向边思路

用了栈优化bellman-ford,T了,用SPFA就A了,然后Dijkstra+heap是过不了(没试过,((V+E)logV)理论是过不了的),用了bellman-ford+stack(传说中比SPFA还不稳定),只是有时有奇效。

#include<cstdio>
#include<queue>
using namespace std;
#define maxn 10009
#define maxm 200009
#define inf 2100000000
queue <int>stk;//一开始用的stack,T了,改成queue时就懒得改变量名了。
int n, m;
int vt=0;
int end[maxm], len[maxm], next[maxm], last[maxn], start[maxm];
int dis[maxn];
bool is_in[maxn], can_arr[maxn];
void adde(int s, int e, int l)
{
	vt++;
	start[vt]=s;
	end[vt]=e;
	len[vt]=l;
	next[vt]=last[s];
	last[s]=vt;
}
void bellman_ford(int s)
{
	int i, cur; 
	for(i=1; i<=n; i++)	dis[i]=inf;
	dis[s]=0;
	stk.push(s);
	is_in[s]=true;
	while(!stk.empty())
	{
		cur=stk.front();
		stk.pop();
		is_in[cur]=false;
		for(i=last[cur]; i; i=next[i])
		{
			if(dis[end[i]]>dis[cur]+len[i])
			{
				dis[end[i]]=dis[cur]+len[i];
				if(!is_in[end[i]])
				{
					stk.push(end[i]);
					is_in[end[i]]=true;
				}
			}
		}
	}
}
inline void _read(int& d)
{
	char t=getchar();bool f=false;
	while(t<'0'||t>'9') {if(t=='-') f=true; t=getchar();}
	for(d=0;t<='9'&&t>='0';t=getchar()) d=d*10+t-'0';
	if(f) d=-d;
}
inline void _out(int d)
{
	int o[30],top=1;
	if(d==0){putchar('0');return ;}
	if(d<0) {putchar('-');d=-d;}
	while(d)
	{
		o[top++]=d%10;
		d/=10;
	}
	for(--top;top;--top) putchar('0'+o[top]);
}
int main()
{
	int i, j;
	int ts, te, s, e;
	scanf("%d%d", &n, &m);
	for(i=1; i<=m; i++)
	{
		_read(ts), _read(te);
		if(ts!=te)
		{
			adde(te, ts, 1);
		}
	}
	scanf("%d%d", &s, &e);
	for(i=1; i<=n; i++)	can_arr[i]=true;
	bellman_ford(e);
	for(i=1; i<=vt; i++)
	{
		if(dis[start[i]]==inf)
		{
			len[i]=inf;
			can_arr[end[i]]=false;
		}
	}
	for(i=1; i<=vt; i++)
	{
		if(can_arr[end[i]]==false)
		{
			len[i]=inf;
		}
	}
	bellman_ford(e);
	printf("%d", dis[s]==inf?(-1):dis[s]);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值