Day 3 AB 题解

A【转自:https://www.cnblogs.com/MengX/p/9762274.html】

题目 Jzzhu and Cities

链接 http://codeforces.com/contest/449/problem/B

题意:给出n个点m条公路k条铁路。

接下来m行 u v w   u->v 距离w

然后k行 v w 1->v 距离w

如果修建了铁路并不影响两点的最短距离,那么修铁路是没必要的

求能删掉多少条铁路

思路:

我们把先按照公路和铁路建图,1到铁路v的距离小于w显然这条铁路是没有必要,或者1到铁路重点v距离有多个等于w及度>1 我们也可以删掉这条铁路

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define fio ios_base::sync_with_stdio(false),cin.tie(0);
 4 #define Pii pair<int,int>
 5 #define INF 0x3f3f3f3f3f3f3f3f
 6 #define ll long long
 7 const int maxn = 100005;
 8 ll dis[maxn];
 9 int head[maxn],To[maxn*20],Len[maxn*20],Next[maxn*20],cnt;
10 int vis[maxn],x[maxn],y[maxn],in[maxn];
11 void add(int u,int v,int w)
12 {
13     Next[++cnt]=head[u];
14     head[u]=cnt;
15     To[cnt]=v;
16     Len[cnt]=w;
17 }
18 int k,n,m;
19 priority_queue<Pii,vector<Pii> , greater<Pii> > q;
20 int dij()
21 {
22     dis[1]=0;
23     q.push(Pii(0,1));
24     while(!q.empty())
25     {
26         Pii tmp=q.top();
27         int u=tmp.second;
28         q.pop();
29         if(vis[u]) continue;
30         vis[u]=1;
31         for(int i=head[u]; i!=-1; i=Next[i])
32         {
33             int v=To[i];
34             int d=Len[i];
35             if(dis[v]>dis[u]+d)
36             {
37                 in[v]=1;
38                 dis[v]=dis[u]+d;
39                     q.push(Pii(dis[v],v));
40             }
41             else if(dis[v]==dis[u]+d)
42                 in[v]++;
43         }
44     }
45     int ans=0;
46     for(int i=1; i<=k; i++)
47     {
48         if(dis[x[i]]<y[i]) ans++;
49         else
50         {
51             if(dis[x[i]]==y[i]&&in[x[i]]>1)
52             {
53                 in[x[i]]--;
54                 ans++;
55             }
56         }
57     }
58     return ans;
59 }
60 int main()
61 {
62     scanf("%d %d %d",&n,&m,&k);
63     for(int i=0; i<=n; i++)
64     {
65         dis[i]=INF;
66     }
67     memset(head,-1,sizeof(head));
68     for(int i=1; i<=m; i++)
69     {
70         int u,v,w;
71         scanf("%d %d %d",&u,&v,&w);
72         add(u,v,w);
73         add(v,u,w);
74     }
75     for(int i=1; i<=k; i++)
76     {
77         int v,w;
78         scanf("%d %d",&x[i],&y[i]);
79         add(1,x[i],y[i]);
80         add(x[i],1,y[i]);
81     }
82     cout<<dij()<<endl;
83     return 0;
View Code

B 【转自:https://blog.csdn.net/weixin_30270889/article/details/97425739】

题目 Planets

链接 https://codeforces.com/problemset/problem/229/B

题意 我们要找一条从1到N的最短路。现在每个点都会在一些时间关闭通道,这些时间不能在这些点上。

思路  设dis[i]表示到达i号传送器的最早时刻.显然,虽然有那么多的出发时刻的限制,但我们还是越早到越好的.因为你到得越早,出发的时间肯定不会比到达的时刻晚的差.所以,就是一个最短路的问题啦.因为数据范围比较大.所以得用dijkstra+优先队列的优化.在出去的时候,只要枚举一遍到达这个点的所有时刻,就能知道它啥时候出发了.因为∑ki<=10^5,根据dijkstra算法也能知道,每个点作为最小值更新其他点只会用到一次.所以这个枚举所有时刻的过程的复杂度是线性的,就只会枚举10^5次。

#include<iostream>  

#include<cstdio>  

#include<cstring>  

#include<string>  

#include<queue>

#include<vector>

#define MAX 100000+10

#define INF 0x3f3f3f3f

using namespace std;

int n, m;

int cnt;

int head[MAX];

vector<int> other[MAX];

int vis[MAX];

int dis[MAX];

struct E {

    int next, from, to, w;

}edge[1000000];

 

void add(int from, int to, int w) {

    edge[cnt].to = to;

    edge[cnt].w = w;

    edge[cnt].next = head[from];

    head[from] = cnt++;

    return;

 

}

int wait(int s, int time) {

    int t = 0;

    for (int i = 0; i < (int)other[s].size(); i++) {

        int tt = other[s][i];

        if (tt < time)

            continue;

        if (tt == time) {

            t++;

            time++;

        }

        else {

            break;

        }

 

    }

    return t;

}

 

void SPFA(int ss) {

    for (int i = 1; i <= n; i++) {

        dis[i] = INF;

 

    }

    vis[ss] = 1;

    dis[ss] = wait(ss, 0);

    queue<int> Q;

    Q.push(ss);

    while (!Q.empty()) {

        int u = Q.front();

        Q.pop();

        vis[u] = 0;

            //注意必须是在这里算出waittime,放在下一个循环里会WA

        int wait_time_for_u = dis[u] + wait(u, dis[u]);

        for (int i = head[u]; i != -1; i = edge[i].next) {

            int v = edge[i].to;

            int w = edge[i].w;

            int arrive_time = wait_time_for_u + w;

            if (dis[v] > arrive_time) {

                dis[v] = arrive_time;

                if (!vis[v]) {

                    vis[v] = 1;

                    Q.push(v);

                }

            }

        }

 

    }

}

 

 

int main(void) {

    while (~scanf("%d%d", &n, &m)) {

        memset(head, -1, sizeof(head));

        memset(vis, 0, sizeof(vis));

        memset(other, 0, sizeof(other));

        cnt = 0;

        for (int i = 1; i <= m; i++) {

            int a, b, d;

            scanf("%d%d%d", &a, &b, &d);

            add(a, b, d);

            add(b, a, d);

        }

        for (int i = 1; i <= n; i++) {

            int t, x;

            scanf("%d", &t);

            while (t--) {

                scanf("%d", &x);

                other[i].push_back(x);

            }

        }

        SPFA(1);

        if (dis[n] == INF) {

            printf("-1\n");

        }

        else {

            printf("%d\n", dis[n]);

 

        }

 

    }

    return 0;

}
View Code

猜你喜欢

转载自www.cnblogs.com/ysq231916/p/12194977.html
ab