codeforces 601A(脑筋急转弯 , 55)

本文探讨了一种算法,用于在给定的完全图中找到一辆火车和一辆汽车从起点到终点的最短路径,图中的边可能是公路或铁路。通过使用广度优先搜索和动态规划的方法,解决了车辆在不重复访问点的情况下同时到达目标点的最短时间问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目意思,给了最多400个点的完全图,但是每条边可能是公路也可能是铁路,求1个火车和一个汽车同时都从1出发到n中间不走到重复点的最短时间.

1 - n 这条边必定是铁路或公路,然后就没有然后了。

下面是自己傻X用压缩了一下转移写的。直接辆车出发最短时间到n 的最小值即答案、

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
#define clr(a , x) memset(a , x , sizeof(a))
#define rep(i , n) for(int i=0;i<(int)n ; i++)
#define rep1(j , x , y) for(int j=(int)x;j<=(int)y;j++)
#define repd(j , y , x) for(int j=(int)y;j>=(int)x;j--)

const int inf = 1e7;
const int N = 410;
int vis[N][N];
vector<int> G[2][N];
int dis[2][N],d[N][N][2];
struct node{
   int x , y, dir;
   node(){}
   node(int x , int y,int dir):x(x) , y(y),dir(dir){}
};
int n, m;
int bfs() {
    rep(i , 2){
         queue<int> Q;
         clr(dis[i], -1);
         dis[i][n] = 0;
         Q.push(n);
         while(!Q.empty()){
              int u = Q.front() ; Q.pop();
              for(auto v : G[i][u]){
                   if(dis[i][v] == -1){
                        dis[i][v] =  dis[i][u] + 1;
                        Q.push(v);
                   }
              }
         }
    }
    int ans = inf;
    clr(d , -1);
    queue<node> Q;
    d[1][1][0] = 0;
    Q.push(node(1 , 1 , 0));
    while(!Q.empty()){
        node u = Q.front(); Q.pop();
        int x = u.x , y = u.y  , dir = u.dir;
        if(u.x == n || u.y == n){
              ans = min(ans , d[x][y][dir]/2 + (x==n ? (dis[1][y] == -1 ? inf : dis[1][y]) : (dis[0][x] == -1 ? inf : dis[0][x])));
              continue;
        }
             if(dir == 0){
                 for(auto i : G[dir][x]){
                   if(d[i][y][1] == -1)
                       d[i][y][1] = d[x][y][dir] + 1 , Q.push(node(i , y , 1));
                 }
             } else {
                for(auto i : G[dir][y]) if(i != x && i!=y){
                  if(d[x][i][0] == -1)
                       d[x][i][0] = d[x][y][dir] + 1 , Q.push(node(x , i , 0));
                }
             }
    }
    return ans==inf ? -1 : ans;
}
int main()
{
   while(scanf("%d %d",&n,&m)==2){
       rep1(i , 1 , m){
           int u , v;
           scanf("%d %d",&u ,&v);
           vis[u][v] = vis[v][u] = 1;
           G[0][u].push_back(v);
           G[0][v].push_back(u);
       }
       rep1(i ,1 , n) rep1(j, 1 , n)
           if(i != j && !vis[i][j]) G[1][i].push_back(j);
       cout<<bfs()<<endl;
   }
   return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值