件名ソース:Loge
タイトル説明
有向グラフGでは、各辺の長さは1です。ここで、始点と終点が与えられたので、グラフの始点から終点までのパスを見つけてください。パスは次の条件を満たしています。
1.パス上のすべてのポイントの外側のエッジが指すポイントは、直接または間接的にエンドポイントに接続されます。
2.条件1が満たされた場合は、パスを最短にします。
注:グラフGには複数のエッジと自己ループが存在する可能性があり、問題により、エンドポイントからのエッジがないことが保証されます。
条件を満たすパスの長さを出力してください。
入力フォーマット
最初の線には、スペースで区切られた2つの整数nとmがあります。これは、グラフにn個のポイントとm個のエッジがあることを意味します。
次のm行には、各行に2つの整数x、yがあり、スペースで区切られています。これは、ポイントxからポイントyにエッジがあることを示します。
最後の行にスペースで区切られた2つの整数sがあり、開始点がsで、終了点がtであることを示します。
出力フォーマット
出力は、タイトルの説明を満たす最短パスの長さを示す整数を含む1行のみです。そのようなパスが存在しない場合は、-1を出力します。
入力例1
3 2
1 2
2 1
1 3
サンプル出力1
-1
入力例2
6 6
1 2
1 3
2 6
2 5
4 5
3 4
1 5
サンプル出力2
3
指示/プロンプト
説明1:
上の図に示すように、矢印は有向道路を示し、点は都市を示します。始点11と終点33が接続されていないため、問題記述を満たすパスが存在しないため、-1-1を出力します。
説明2:
上の図に示すように、条件を満たすパスは1-> 3-> 4-> 5です。ポイント2はエッジをポイント6に接続し、ポイント6はエンドポイント5に接続されていないため、ポイント2を応答パスに含めることはできないことに注意してください。
【データ範囲】
データの30%について、0 <n≤10、0 <m≤20;
データの60%について、0 <n≤100、0 <m <m≤2000;
100%データの場合、0 <n≤10000、0 <m≤200000、0 <x、y、s、t≤n、x、s≠t。
アイデア:
参照の解決策は、この問題
なければならないのである:
1、すべての反対側、エンドからのED開始BFS、エンド・マーキング編の開始点が来るかもしれません
2.各ポイントを列挙します。ポイントがマークされていない場合は、その出力エッジをそれぞれ列挙します(反転)。ポイントがマークされている場合は、マークされているポイントが不正であることを意味します。削除、
2番目の配列マークを付けることをお勧めします。配列内のポイントを削除すると後遺症タイプになります。ポイントがマークされ始めると、シリアル番号の小さいポイントから削除され、アクセスされると、最初にマークされていなかったポイントとみなされ、合法的なポイントは削除されます。
上記は_kong_のブログからのものです
3.リーガルポイント上の単一のソースポイントから最短パスを取ります
コード:(少し長いですが、アイデアは明確です)
#include<bits/stdc++.h>
using namespace std;
const int N=1e4+10;
int n,m,st,ed,vis[N],vis1[N],dis[N],x[N],y[N];
vector <int> a[N],b[N];
queue <int> q;
void bfs(int s) //反向标记
{
q.push(s);
while (!q.empty())
{
int t=q.front();
q.pop();
vis[t]=1;
for (int i=0;i<b[t].size();i++)
{
int to=b[t][i];
if (vis[to]==0)
{
q.push(to);
vis[to]=1;
}
}
}
}
void cancel()
{
memcpy(vis1,vis,sizeof(vis));
for (int i=1;i<=n;i++)
if (vis[i]==0)
{
for (int j=0;j<b[i].size();j++)
vis1[b[i][j]]=0;
}
for (int i=1;i<=n;i++)
{
if (vis1[i]==0)
{
for (int j=0;j<a[i].size();j++)
a[i][j]=0;
}
}
}
void init()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
if (x==y) continue;
a[x].push_back(y);//正向边
b[y].push_back(x);//反向边
}
scanf("%d%d",&st,&ed);
}
void spfa(int s)
{
while (!q.empty()) q.pop();
for (int i=1;i<=n;i++) dis[i]=99999999,vis[i]=0;
dis[s]=0;
q.push(s);
vis[s]=1;
while (!q.empty())
{
int t=q.front();
q.pop();
vis[t]=1;
for (int i=0;i<a[t].size();i++)
{
int to=a[t][i];
if (dis[to]>dis[t]+1)
{
dis[to]=dis[t]+1;
if (vis[to]==0)
{
q.push(to);
vis[to]=1;
}
}
}
}
}
int main()
{
init();
bfs(ed); //从终点反向标记
if (vis[ed]==0) //起点无法到达终点就直接结束程序
{
cout<<-1<<endl;
return 0;
}
cancel();//撤去不符合条件的点
spfa(st);//单元点最短路
if (dis[ed]==99999999) cout<<-1<<endl;
else cout<<dis[ed]<<endl;
return 0;
}