您的位置:首页 > 编程语言

景驰无人驾驶 1024 编程邀请赛 A 题 【最短路 + 思维】

2017-10-31 11:24 351 查看
传送门

//题意: 就是n个点, 有些地下通道可以挡雨, 有些普通路面不能, 从1出发到n点, 问在保证总距离小于L的情况下, 淋雨的最小距离是多少.

//思路: 我的做法是标记每条路它是地下通道还是普通路面, 然后直接跑最短路就是了(因为这样跑, 可以将所有可以到达终点的路径都可遍历一遍, 所以一定可以出一个最优结果), 然后为了区分一个淋雨距离和总距离, 需要用到两个数组分别进行标记, 总距离是用来跑dij和判断与L的关系的, 而淋雨距离则是最后的答案, 然后分别进行更新即可. 注意标记的用法, 细节请看代码.

AC Code

const int inf = 0x3f3f3f3f; //用这个可以直接mem
const int maxn = 1e2+5;
int cas=1;
int cnt,head[maxn];
struct node
{
int to,w,next,flag;
bool operator < (const node& a) const {
return a.w < w;
}
}e[maxn*maxn+maxn];
void add(int u,int v,int w,int flag)
{
e[cnt] = (node){v,w,head[u],flag};
head[u] = cnt++;
}
int n,m1,m2,L;
bool vis[maxn];
int dis1[maxn],dis2[maxn];
void dij(int st,int ed)
{
priority_queue<node> q;
Fill(dis1,inf); Fill(dis2,inf); Fill(vis,0);
dis1[st] = 0; dis2[st] = 0;
q.push((node){st, 0, 0, 0});
while (!q.empty()) {
node u = q.top();
q.pop();
if(vis[u.to]) continue;
vis[u.to] = 1;

for (int i = head[u.to]; ~i; i = e[i].next) {
node k = e[i];
int w = dis1[u.to] + k.w;
//u.flag决定的是u及u之前有多少条地下通道,而k.flag决定的是当前这条路是不是地下通道.
if(w <= L && dis2[k.to] > w - u.flag - k.flag) {
dis1[k.to] = w;
dis2[k.to] = w - u.flag - k.flag;
q.push((node){k.to, dis1[k.to] , 0, u.flag+k.flag});
}
}
}
if(dis2[ed] == inf) cout << "-1" << endl;
else cout << dis2[ed] << endl;
}
void solve()
{
cnt = 0; Fill(head,-1);
scanf("%d%d%d%d",&n,&m1,&m2,&L);
for(int i=1;i<=m1;i++) {
int u,v;
scanf("%d%d",&u,&v);
add(u,v,1,1); add(v,u,1,1);
}
for(int i=1;i<=m2;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w,0); add(v,u,w,0);
}
dij(1,n);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: