链接:https://ac.nowcoder.com/acm/contest/699/E
来源:牛客网
题目描述
某华大学小飞中奖了!!!奖品是一张免费飞机票,唯一遗憾的是,这张飞机票有限定区间,需要从k个区间中选择其一。小飞打算高高兴兴的出去玩啦,但是,从s地出发,去往e地,可能没有直达的飞机票,可能需要转机(所有飞机线路都是无向的),小飞毕竟是个学生党,出去玩首先得考虑省钱,所以,小飞遇到麻烦了,请帮小飞计算最便宜的一条路线,小飞会很感激你的。
输入描述:
第一行为三个整数n,s,e,n表示n个不同城市的飞机场,s为出发点,e为目的地。(1<=n<=1000, 1<=s,e<=n) 第二行为一个整数m,表示m条普通飞机线路,接下来的m行描述每条线路,每行包含三个整数a、b、c,a、b代表普通飞机线路两端,c表示价格。(1<=m<=1000, 1<=a,b<=n, 1<=c<=1000) 接下来的一行为一个整数k,表示k个免费机票的航线区间, 然后k行来描述每条免费航线,每行两个整数a’、b’, 分别代表免费航线两端。(1<=k<=1000, 1<=a’,b’<=n)
输出描述:
每个测试数据有两行输出,第一行为是否使用免费飞机票,是则输出“Yes”,否则输出“No”。第二行输出总共花费。
示例1
输入
复制
4 1 4 3 1 2 1 1 3 2 2 4 3 1 3 4
输出
复制
Yes 2
示例2
输入
复制
7 1 7 5 1 4 1 1 5 2 1 7 10 4 7 8 5 7 5 2 2 4 6 7
输出
复制
No 7
我的思路很简单,就是建完图之后跑一次最短路,然后再分别跑k次,对比一下就行了
有个地方要注意的是,在你加过一次免费边 跑完dijk的时候,要把这个边删掉,再加剩下的
因为题目要求只能选k中的一条
代码写的比较丑。。。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e4+5;
const int maxm=1e4+5;
int head[maxn],vis[maxn],cnt,n,m,s,ee;
ll dis[maxn];
struct edge
{
int to,next,dis;
}e[maxm];
void addedge(int u,int v,int w)
{
cnt++;
e[cnt].to=v;
e[cnt].dis=w;
e[cnt].next=head[u];
head[u]=cnt;
}
struct node
{
int pos;ll dis;
bool operator <(const node &x)const
{
return x.dis<dis;
}
};
priority_queue<node>q;
inline void dijkstra()
{
for(int i=1;i<=n;i++) dis[i]=0x3f3f3f3f;
dis[s]=0;
q.push((node){s,0});
while(!q.empty())
{
node tmp=q.top();
q.pop();
int x=tmp.pos;
if(vis[x]) continue;
vis[x]=1;
for(int i=head[x];i;i=e[i].next)
{
int y=e[i].to;
if(dis[y]>dis[x]+e[i].dis)
{
dis[y]=dis[x]+e[i].dis;
if(!vis[y])
q.push((node){y,dis[y]});
}
}
}
}
int uu[maxn],vv[maxn],ww[maxn]; int cntt;
int main()
{
scanf("%d%d%d%d",&n,&s,&ee,&m);
for(int i=0;i<m;i++)
{
int u,v,w;scanf("%d%d%d",&u,&v,&w);
addedge(u,v,w);
addedge(v,u,w);
uu[cntt]=u,vv[cntt]=v,ww[cntt]=w;cntt++;
}
dijkstra();
ll ans=dis[ee];
ll anss=0x3f3f3f3f;
int k;scanf("%d",&k);
for(int i=0;i<k;i++)
{
int u,v;scanf("%d%d",&u,&v);
int x=e[head[u]].to; int y=e[head[u]].to;
addedge(u,v,0);
addedge(v,u,0);
memset(vis,0,sizeof vis);
dijkstra();
anss=min(anss,dis[ee]);
memset(head,0,sizeof head);
memset(e,0,sizeof e);
cnt=0;
for(int j=0;j<cntt;j++) addedge(uu[j],vv[j],ww[j]),addedge(vv[j],uu[j],ww[j]);
}
if(ans!=anss) printf("Yes\n%d\n",min(ans,anss));
else printf("No\n%d\n",ans);
return 0;
}