$Sol$
首先把不符合条件一的点去掉然后跑$SPFA$就好了叭.
如何判断点是否符合条件一呢?先连反边,记录每个点的入度,然后从终点开始$dfs$,记录每个点被到达的次数,若到达的次数小于它的入读那么就是不满足题意的.
为啥$Noip2014$有$4$道连我都觉得很水的题.
$Code$
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<algorithm> #define il inline #define Rg register #define go(i,a,b) for(Rg int i=a;i<=b;++i) #define yes(i,a,b) for(Rg int i=a;i>=b;--i) #define e(i,u) for(Rg int i=b[u];i;i=a[i].nt) #define mem(a,b) memset(a,b,sizeof(a)) #define ll long long #define db double #define inf 2147483647 using namespace std; il int read() { Rg int x=0,y=1;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();} while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();} return x*y; } const int N=10010,M=200010; int n,m,b[N],ct,du[N],s,t,vis[N],dis[N]; bool fl[N]; queue<int>q; struct nd1{int u,v;}eg[M]; struct nd{int v,nt;}a[M]; il void add(int u,int v){a[++ct]=(nd){v,b[u]};b[u]=ct;} il void dfs(int u) { e(i,u) { Rg int v=a[i].v;vis[v]++; if(vis[v]>1)continue; dfs(v); } } il void SPFA() { mem(vis,0);mem(dis,63); vis[s]=1;dis[s]=0;q.push(s); while(!q.empty()) { Rg int u=q.front();q.pop();vis[u]=0; e(i,u) { Rg int v=a[i].v; if(!fl[v])continue; if(dis[v]>dis[u]+1) { dis[v]=dis[u]+1; if(!vis[v]){vis[v]=1;q.push(v);} } } } } il bool cmp(nd1 x,nd1 y){return x.u==y.u?x.v<y.v:x.u<y.u;} int main() { n=read(),m=read(); go(i,1,m) { Rg int u=read(),v=read(); if(u==v)continue; eg[i]=(nd1){u,v};//add(v,u);du[u]++; } sort(eg+1,eg+m+1,cmp); Rg int nm=0; go(i,1,m) { if(eg[i].u==eg[i-1].u && eg[i].v==eg[i-1].v){nm++;continue;} add(eg[i].v,eg[i].u);du[eg[i].u]++; } m-=nm; s=read(),t=read();swap(s,t); vis[s]=1;dfs(s); go(i,1,n)if((vis[i]==du[i]&&vis[i])||i==s)fl[i]=1; if(!fl[s]){printf("-1\n");return 0;} SPFA(); if(dis[t]>M)printf("-1\n"); else printf("%d\n",dis[t]); return 0; }View Code