【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;
}