题目链接
读完题目之后可以发现,需要做两件事情。
1 **·挑出满足条件的点,打上标记。
2·**求从S到T的最短路
接下来分布解决这两个问题
求满足要求的点
首先需要知道每个点是否与T连通,用dfs可以解决,我们需要建立逆向思维,见一个反图。
由T点出发执行一次dfs就可以解决问题。代码如下:
void dfs(int x){
book[x]=1;
for(int i=rhead[x] ; i ; i=rnext[i]){
int v=rver[i];
if(book[v]) continue;
dfs(v);
}
}//book标记过的数都与T连通。
接下来判定是否点的出边所指向的点都直接或间接与终点连通。我们需要建一个新的标记数组,因为
直接在book数组上修改会有后效性。代码如下:
//pd[]为新的判定数组
for(int i=1;i<=n;i++){
int flag=1;
if(i==t){
pd[i]=1;
continue;
}
if(book[i]){
for(int k=head[i];k;k=next[k]){
int v=ver[k];
if(book[v]==0){ //若出边所指向的点不与T点连通,则该点不应出现在路径中。
flag=0;
break;
}
}
}
if(flag) pd[i]=1;
else pd[i]=0;
}//最后被标记为一的点即为所求。
最短路
最短路个人偏好迪杰斯特拉算法,此题数据应该用堆优化的迪杰斯特拉算法。代码如下:
struct node{
int bh,w;
friend bool operator <(node a,node b){
return a.w>b.w; //定义友元函数,规定优先队列的优先级。
}
};
memset(book,0,sizeof(book);
memset(d,0x3f3f,sizeof(d));
priority_queue <node> q;
node cun;
cun.bh=s;
cun.w=0;
q.push(cun);
d[s]=0;
while(q.size()){
int num=q.top().bh;
q.pop();
if(book[num]) continue;
book[num]=1;
for(int i=head[num];i;i=next[i]){
int v=ver[i];
if(pd[v]==0) continue;//若不应出现在最短路径中则跳过。
if(d[v]>d[num]+1){
d[v]=d[num]+1;
cun.bh=v; cun.w=d[v];
q.push(cun);
}
}
}
最后是本人的完整代码:
#include<bits/stdc++.h>
using namespace std;
struct node{
int bh,w;
friend bool operator <(node a,node b){
return a.w>b.w;
}
};
int n,m,s,t;
int head[100010],rhead[100010],next[200010],rnext[200010],ver[200000+5],rver[200000+5];
int tot1,tot2;
int book[100010],pd[100010],d[100010];
void add1(int u,int v){
tot1++;
ver[tot1]=v;
next[tot1]=head[u];
head[u]=tot1;
}
void add2(int u,int v){
tot2++;
rver[tot2]=v;
rnext[tot2]=rhead[u];
rhead[u]=tot2;
}
void dfs(int x){
book[x]=1;
for(int i=rhead[x];i;i=rnext[i]){
int v=rver[i];
if(book[v]) continue;
dfs(v);
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int a,b;
scanf("%d%d",&a,&b);
add1(a,b); add2(b,a);
}
scanf("%d%d",&s,&t);
dfs(t);
for(int i=1;i<=n;i++){
int flag=1;
if(i==t){
pd[i]=1;
continue;
}
if(book[i]){
for(int k=head[i];k;k=next[k]){
int v=ver[k];
if(book[v]==0){
flag=0;
break;
}
}
}
if(flag) pd[i]=1;
else pd[i]=0;
}
memset(book,0,sizeof(book));
memset(d,0x3f3f,sizeof(d));
priority_queue <node> q;
node cun;
cun.bh=s;
cun.w=0;
q.push(cun);
d[s]=0;
while(q.size()){
int num=q.top().bh;
q.pop();
if(book[num]) continue;
book[num]=1;
for(int i=head[num];i;i=next[i]){
int v=ver[i];
if(pd[v]==0) continue;
if(d[v]>d[num]+1){
d[v]=d[num]+1;
cun.bh=v; cun.w=d[v];
q.push(cun);
}
}
}
if(d[t]<0x3f3f)
printf("%d",d[t]);
else
printf("-1");
}