Gym 100812G Short Path

来源:互联网 发布:服装设计cad软件 编辑:程序博客网 时间:2024/05/17 10:42

Gym 100812G Short Path

最短路问题 多源最短路

传送门:CodeForce

传送门:HustOJ

题意

无向图,点有0/1之分。找出距离最近的一对1。输出距离与点对。


思路

分析:
SPFA变形,单源最短路转化为,所有点到某个1之间的最短路,然后枚举中间边,找合法解。
解法:
SPFA,将所有1点同时初始化为0,同时进栈进行松弛,最终可求出每一点到最近的1的距离及最近的1是哪个点。然后遍历所有边,若一条边两边都是1,则路径合法;若两边都是0,且两边最近的1不同点,则路径合法;若一边0一边1,且两边最近的1不同点,则路径合法。最后将所有合法路径取最小值即为答案。

  • 首先,spfa求的是某一点到其他所有点的最短路,最开始初始化队列时将源点放入队列。如果开始时放多个源点进队列,那么算法求出的是其他所有点到任意一个源点的最短距离。
  • 所以我们把所有的1都放到队列里,求出的就是每一个0点到其最近的1的距离,顺带可以求出最近的1是谁。(对于一个1点,他最近的1就是本身)
  • 然后枚举边,如果一条边两侧的1点号是不同的,那么这条路径,记录路径长度与两端点。取最小的即可。

代码

#include <cstdio>#include <cstdlib>#include <iostream>#include <algorithm>#include <string>#include <cstring>#include <vector>#include <cmath>#include <queue>#include <stack>#define _ ios_base::sync_with_stdio(0);cin.tie(0);#define M(a,b) memset(a,b,sizeof(a));using namespace std;const int MAXN=100005;const int oo=0x3f3f3f3f;typedef long long LL;const LL loo=4223372036854775807ll;typedef long double LB;int a[MAXN];struct Edge{    int to, cost;    Edge(){}    Edge(int _a, int _b) { to=_a;cost=_b; }};vector<Edge> G[MAXN];int pre[MAXN];LL dis[MAXN];int vis[MAXN];void spfa(int n,int m){    M(dis, 0x3f);M(pre, -1);M(vis, 0);    queue<int> que;    for(int i=1;i<=n;i++)        if(a[i])        {            dis[i]=0;pre[i]=i;vis[i]=1;            que.push(i);        }    while(!que.empty())    {        int temp=que.front();que.pop();vis[temp]=0;        for(Edge u : G[temp])        {            int tt=u.to;int cc=u.cost;            if(dis[tt]>dis[temp]+cc)            {                pre[tt]=pre[temp];dis[tt]=dis[temp]+cc;                if(vis[tt]==0) { que.push(tt);vis[tt]=1; }            }        }    }}int main(){    _    int n;    while(cin>>n)    {        int m;cin>>m;        M(a, -1);        for(int i=1;i<=n;i++) cin>>a[i];        for(int i=0;i<m;i++)        {            int ta, tb, tc;cin>>ta>>tb>>tc;            G[ta].push_back(Edge(tb, tc));            G[tb].push_back(Edge(ta, tc));        }        spfa(n, m);        LL d=loo;int f, t;        for(int i=1;i<=n;i++)        {            for(Edge u : G[i])            {                int tt=u.to;int cc=u.cost;                if(pre[tt]!=pre[i])                {                    if(d>dis[tt]+dis[i]+cc)                    {                        d=dis[tt]+dis[i]+cc;                        f=pre[tt], t=pre[i];                    }                }            }        }        if(d>=loo) cout<<"No luck at all"<<endl;        else        {            cout<<d<<endl;            cout<<f<<' '<<t<<endl;        }    }    return 0;}
0 0