码迷,mamicode.com
首页 > 其他好文 > 详细

暑假 D4T1 path(反向建图 dijkstra)

时间:2019-07-13 20:04:22      阅读:84      评论:0      收藏:0      [点我收藏+]

标签:间接   include   signed   front   input   unsigned   har   max   first   

Description

众所周知,Bfk 经常为找不到路而烦恼
Bfk 终于迎来了它高中以来第一个完整的暑假,它决定从假期里抽出一段时间去日本
旅游。可是,对于连教师宿舍都找不到的 Bfk 来说,在旅途中不迷路是一件很困难的事
情。为了避免迷路的尴尬,Bfk 早早的就规划起了它的行程。它将日本的地图抽象成了一
张 n 个点 m 条边的有向图,并在上面选定了行程的起点和终点,但它在规划旅行路径时却
犯了难。它希望路径上的点都满足该点的出边所指向的点都能直接或间接的到达终点,这
样即使它走错了路,也能重新规划路线到达终点。另外,它还希望旅行的路程尽可能短,
以便节约更多的时间预习大学课程。
现在,Bfk 找到了你,希望你能帮帮它。它不想为难你,因此你不用输出具体的方
案,只需要告诉它满足条件的路径的最短长度就可以了

Input

第一行两个整数 ?? 和 ?? ,含义如题
接下来 m 行,每行三个整数 ??, ??, ?? ,描述一条从 ?? 指向 ?? 的单向边,长度为??
接下来一行两个整数 ??,??,表示起点和终点

Output

输出一行一个数字,表示满足要求的路径的最短长度
特别的,如果不存在这样的路径,则输出“-1”(不含引号)

题解

由于做过最优贸易,所以对于点到达终点的条件可以很容易转换,建立反图,从t跑。

考虑所有路径上的点满足出边的点都能到终点的条件,可以在dfs时记录到达该节点的次数,

该次数等同于这个点出边的点可以到t的个数。

最后再用满足条件的点建出正向的图,跑最短路即可。

于是愉快的spfa和只是大的大数据。

#include<bits/stdc++.h>
using namespace std;

const int maxn=100005;
int n,m,s,t;
vector<pair<int,int> >e[maxn],a[maxn];
int chu[maxn],cnt[maxn];

template<class T>inline void read(T &x){
    x=0;char ch=getchar();
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
}

void dfs(int u){
    //printf("%d ",u);
    for(unsigned int i=0;i<a[u].size();i++){
        int v=a[u][i].first;
        cnt[v]++;
        if(cnt[v]==1)
         dfs(v);
    }
}

queue<int> q;
bool vis[maxn];
int dis[maxn];

void spfa(){
    for(int i=1;i<=n;i++) dis[i]=0x7ffffff;
    q.push(s);
    vis[s]=true;dis[s]=0;
    while(!q.empty()){
        int x=q.front();
        q.pop();
        vis[x]=false;
        for(unsigned int i=0;i<e[x].size();i++){
            int y=e[x][i].first;
            if(dis[y]>dis[x]+e[x][i].second){
                dis[y]=dis[x]+e[x][i].second;
                if(!vis[y]) {vis[y]=true;q.push(y);}
            }
        }
    }
}

int main(){
    freopen("path.in","r",stdin);
    freopen("path.out","w",stdout);
    read(n);read(m);
    for(int i=1;i<=m;i++){
        int x,y,z;
        read(x);read(y);read(z);
        if(x==y) continue;
        chu[x]++;
        a[y].push_back(make_pair(x,z));
    }
    read(s);read(t);
    cnt[t]=1;
    dfs(t);
    //for(int i=1;i<=n;i++) printf("%d %d\n",cnt[i],chu[i]);
    if(!cnt[s]) {printf("-1");return 0;}
    cnt[t]=chu[t];
    for(int i=1;i<=n;i++)
     if(cnt[i]==chu[i]){
         for(unsigned int j=0;j<a[i].size();j++){
             int x=a[i][j].first,y=a[i][j].second;
             if(chu[x]==cnt[x]){
                 e[x].push_back(make_pair(i,y));
                 //printf("%d %d %d\n",i,x,y);             
        }
              
         }
    }
    spfa();
    if(dis[t]==0x7ffffff) printf("-1");
    else printf("%d",dis[t]);
}
/*6 7
2 1
3 1
4 1
4 1
5 1
4 1
6 1
4
*/

关于spfa,他死了

都9102年了,还有人卡spfa

只有用堆优化的dijkstra

#include<bits/stdc++.h>
using namespace std;

const int maxn=1000005;
#define ll long long
int n,m,s,t;
vector<pair<int,ll> >e[maxn],a[maxn];
int chu[maxn],cnt[maxn];

template<class T>inline void read(T &x){
    x=0;char ch=getchar();
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
}

void dfs(int u){
    //printf("%d ",u);
    for(unsigned int i=0;i<a[u].size();i++){
        int v=a[u][i].first;
        cnt[v]++;
        if(cnt[v]==1)
         dfs(v);
    }
}

priority_queue < pair < ll,int >,vector < pair < ll,int > >,greater < pair < ll ,int > > > q;
bool vis[maxn];
ll dis[maxn];

void dijkstra(){
    for(int i=1;i<=n;i++) dis[i]=0x7fffffff;
    dis[s]=0;
    q.push(make_pair(dis[s],s));
    while(!q.empty()){
        int x=q.top().second;
        q.pop();
        if(vis[x]) continue;
        vis[x]=true;
        for(unsigned int i=0;i<e[x].size();i++){
            int y=e[x][i].first;
            if(vis[y]) continue;
            if(dis[y]>dis[x]+e[x][i].second){
                dis[y]=dis[x]+e[x][i].second;
                q.push(make_pair(dis[y],y));
            }
        }
    }
}

int main(){
    freopen("path.in","r",stdin);
    freopen("path.out","w",stdout);
    read(n);read(m);
    for(int i=1;i<=m;i++){
        int x,y;
        ll z;
        read(x);read(y);read(z);
        if(x==y) continue;
        chu[x]++;
        a[y].push_back(make_pair(x,z));
    }
    read(s);read(t);
    cnt[t]=1;
    dfs(t);
    //for(int i=1;i<=n;i++) printf("%d %d\n",cnt[i],chu[i]);
    if(!cnt[s]) {printf("-1");return 0;}
    cnt[t]=chu[t];
    for(int i=1;i<=n;i++)
     if(cnt[i]==chu[i]){
         for(unsigned int j=0;j<a[i].size();j++){
             int x=a[i][j].first,y=a[i][j].second;
             if(chu[x]==cnt[x]){
                 e[x].push_back(make_pair(i,y));
                 //printf("%d %d %d\n",i,x,y);             
        }
              
         }
    }
    dijkstra();
    if(dis[t]==0x7fffffff) printf("-1");
    else printf("%lld",dis[t]);
}
/*6 7
1 2 1
1 3 1
3 4 1
2 4 1
3 5 1
5 4 1
5 6 1
1 4
*/

 

暑假 D4T1 path(反向建图 dijkstra)

标签:间接   include   signed   front   input   unsigned   har   max   first   

原文地址:https://www.cnblogs.com/sto324/p/11181659.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!