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

来源:互联网 发布:mac 更改文件夹位置 编辑:程序博客网 时间:2024/05/17 06:50

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

AC Code

const int inf = 0x3f3f3f3f; //用这个可以直接memconst 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);}
阅读全文
0 0