美团测试题 T3

美团这个卖外卖的还考这些~~长见识!

题目描述
给定一个n个点m条无向边的连通图,每条边长度均为1
现在要求你删除尽量多的边,使得从s1到t1的最短路径不超过l1,并且s2到t2的最短路径不超过l2。
如果没有满足条件的方案,输出-1。
输入格式
第一行输入两个正整数n,m表示无向图的点数和边数。
接下来m行每行两个整数a,b表示节点a和节点b之间有一条边(点从1开始编号)。
接下来一行三个整数s1,t1,l1。
接下来一行三个整数s2,t2,l2。
1<=si,ti<=n
0<=li<=n
输入数据保证图连通并且没有重边和自环。
输出格式
输出一行一个整数,表示最多能够删多少条边,如果没有合法方案输出-1。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<vector>
#include<queue>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int N=1e5+10,INF=0x3f3f3f;
int n,a[N],b[N];
struct Edge{
    int from,to,val,next,jud;
    Edge(int from=-1,int to=-1,int val=0,int next=-1,int jud=-1):from(from),to(to),val(val),next(next),jud(jud){}
}e[N*2];
int len=0,last[N];
void add(int from,int to,int val,int jud) {
    e[++len]=Edge(from,to,val,last[from],jud); last[from]=len;
}
void build_Graph() {
    int w=-n+1;
    for (int i=0;i<n;i++) {
    if(i+a[i]>=0&&i+a[i]<n) add(i,i+a[i],w,1);
    w++;
    if(i+b[i]>=0&&i+b[i]<n) add(i,i+b[i],-w+1,0);
    }
}
int inq[N],dis[N],vis[N];
struct road{
    int id,node;
}pre[N];
int SPFA(int s) {
    memset(inq,0,sizeof(inq));
    memset(vis,0,sizeof(vis));
    fo(i,0,n-1) {dis[i]=INF;pre[i].node=-1;}
    fo(i,0,n-1) dis[i]=INF;
    queue<int>q;
    dis[s]=0;
    q.push(s); inq[s]=1; 
    vis[s]++;
    while(!q.empty()) {
        int cur=q.front();
        vis[cur]++;
        if(vis[cur]>=n) return 0;  
        q.pop();
        inq[cur]=0;
        for(int i=last[cur];i;i=e[i].next) {
            int id=e[i].to;
            if(dis[id]>dis[cur]+e[i].val) {
                dis[id]=dis[cur]+e[i].val;
                pre[id].id=e[i].jud;
                pre[id].node=cur;
                if(!inq[id]) {
                    q.push(id);
                    inq[id]=1;
                }
            }
        }
    }
    return 1;
}
//bool SPFA(int s){
//  int num[MAXN];
//  fo(i,1,n) dis[i]=1e5;
//  memset(vis,0,sizeof(vis));
//  memset(num,0,sizeof(num));
//  queue<int> q;
//  dis[s]=0;q.push(s);vis[s]=1;
//  while(!q.empty()){
//      int cur=q.front();
//      q.pop();
//      vis[cur]=0;
//      num[cur]++;
//      if(num[cur]>n) return 0;
//    for(int i=last[cur];i;i=e[i].next)
//  {
//    int id=e[i].to;
//    if(dis[id]>dis[cur]+e[i].val)
//    {
//      dis[id]=dis[cur]+e[i].val;
//      if(!vis[id]){
//        q.push(id);
//        vis[id]=1;
//      }
//    }
//  }
//  }
//  return -1;
//}
int main() {
    scanf("%d",&n);
    fo(i,0,n-1) scanf("%d",&a[i]);
    fo(i,0,n-1) scanf("%d",&b[i]);
    build_Graph();
//  SPFA(0);
//  printf("%d",dis[6]);
//  fo(i,1,len) {
//      printf("e[%d].from=%d .to=%d .val=%d .next=%d .jud=%d\n",i,e[i].from,e[i].to,e[i].val,e[i].next,e[i].jud);
//  }

    if(!SPFA(0)) {
        printf("Infinity!\n");
    }
    else {
        if(dis[n-1]==INF) printf("No solution!\n");
        else {
            int x=n-1;
            int ans[N],cnt=0;
            while(x!=0) {
                ans[++cnt]=pre[x].id;
                x=pre[x].node;
            }
            char key[N],tot=0;
            fo(i,1,cnt) {
                if(ans[i]) key[++tot]='a';
                else key[++tot]='b';
            }
            for(int i=tot;i>=1;i--) {
                printf("%c",key[i]);
            }
            cout<<endl;
        }
    }
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值