• 图论-某图论专练 Round3 (April, 2018)


    我实在太弱啦 OrzOrz ,B题负权回路没看出来,D题写爆,平时太懒练少了吧。

    A. Floyd裸题, O(N^3) 。

    B. Bellman-Ford 判负权回路,注意麦田间的小路是双向边,而虫洞是单向边,这是个巨大的坑点。

    C. 贪心裸题,最少线段覆盖,也可以用图论做。

    D. 二分答案 + 图论。二分一个最长电线长度,将大于这个长度的边权值置为 1 ,小于等于这个长度的边权置为 0,从

    1 号点开始跑一遍最短路,Dis[N] 即为最少的需要电信公司免费搭建的电线数量。Dis[N] <= K 时,二分的答案是合理的。

     1 #include <stdio.h>
     2 
     3 const int INF = 1e9;
     4 
     5 int G[250][250], Dis[250];
     6 
     7 int main()
     8 {
     9     int N, M, Q, t1, t2, t3, i, j, k;
    10     scanf("%d%d%d", &N, &M, &Q);
    11     for (i = 1; i <= N; ++i) {
    12         scanf("%d", &Dis[i]);
    13         for (j = 1; j <= N; ++j)
    14             G[i][j] = INF;
    15         G[i][i] = 0;
    16     }
    17     for (i = 1; i <= M; ++i) {
    18         scanf("%d%d%d", &t1, &t2, &t3);
    19         if (t1 == t2) continue;
    20         if (Dis[t1] >= t3) G[t1][t2] = 1;
    21         if (Dis[t2] >= t3) G[t2][t1] = 1;
    22     }
    23     for (k = 1; k <= N; ++k)
    24         for (i = 1; i <= N; ++i)
    25             for (j = 1; j <= N; ++j)
    26                 if (G[i][j] > G[i][k] + G[k][j])
    27                     G[i][j] = G[i][k] + G[k][j];
    28     while (Q--) {
    29         scanf("%d%d", &t1, &t2);
    30         if (G[t1][t2] == INF)
    31             printf("no way
    ");
    32         else
    33             printf("%d
    ", G[t1][t2]);
    34     }
    35     return 0;
    36 }
    A
     1 #include <stdio.h>
     2 #include <vector>
     3 #include <queue>
     4 
     5 using namespace std;
     6 
     7 const int _N = 700;
     8 
     9 const int INF = 1e9;
    10 
    11 struct Node {
    12     int v, w;
    13     Node(int v, int w):
    14         v(v), w(w) { }
    15 };
    16 
    17 vector<Node> G[_N];
    18 queue<int> Q;
    19 int Dis[_N], N, GGG[_N][_N], book[_N], cnt[_N];
    20 
    21 inline void Ins(int t1, int t2, int t3) { G[t1].push_back(Node(t2, t3)); return; }
    22 
    23 bool Bellman(int Beg)
    24 {
    25     for (int i = 1; i <= N; ++i) Dis[i] = INF, book[i] = false, cnt[i] = 0;
    26     while (!Q.empty()) Q.pop();
    27     Dis[Beg] = 0, book[Beg] = true, Q.push(Beg), cnt[Beg] = 1;
    28     while (!Q.empty()) {
    29         int p = Q.front(); book[p] = false; Q.pop();
    30         vector<Node>::iterator it;
    31         for (it = G[p].begin(); it != G[p].end(); ++it)
    32             if (Dis[it->v] > Dis[p] + it->w) {
    33                 Dis[it->v] = Dis[p] + it->w;
    34                 if (book[it->v]) continue;
    35                 Q.push(it->v), book[it->v] = true;
    36                 if (++cnt[it->v] == N+1) return true;
    37                 if (it->v == Beg && Dis[it->v] < 0) return true;
    38             }
    39     }
    40     return false;
    41 }
    42 
    43 int main()
    44 {
    45     int T;
    46     scanf("%d", &T);
    47     while (T--) {
    48         int t1, t2, t3, A, B, i, j;
    49         scanf("%d%d%d", &N, &A, &B);
    50         for (i = 1; i <= N; ++i) G[i].clear();
    51         
    52         for (i = 1; i <= N; ++i)
    53             for (j = 1; j <= N; ++j)
    54                 GGG[i][j] = INF;
    55                 
    56         while (A--) {
    57             scanf("%d%d%d", &t1, &t2, &t3);
    58             GGG[t1][t2] = min(GGG[t1][t2], t3);
    59             GGG[t2][t1] = min(GGG[t2][t1], t3);
    60         }
    61         
    62         while (B--) {
    63             scanf("%d%d%d", &t1, &t2, &t3);
    64             GGG[t1][t2] = min(GGG[t1][t2], -t3);
    65         }
    66         
    67         for (i = 1; i <= N; ++i)
    68             for (j = 1; j <= N; ++j)
    69                 if (GGG[i][j] != INF)
    70                     Ins(i, j, GGG[i][j]);
    71         
    72         if (Bellman(1))
    73             printf("YES
    ");
    74         else
    75             printf("NO
    ");
    76     }
    77     return 0;
    78 }
    B
     1 #include <stdio.h>
     2 #include <vector>
     3 #include <queue>
     4 #include <algorithm>
     5 
     6 using namespace std;
     7 
     8 const int _N = 1100000;
     9 
    10 typedef long long LL;
    11 
    12 const long long INF = 99999999999999LL;
    13 
    14 struct Node {
    15     LL v, w;
    16     Node(LL v, LL w):
    17         v(v), w(w) { }
    18 };
    19 
    20 struct StrDis {
    21     LL v, dis;
    22     StrDis(LL v, LL dis):
    23         v(v), dis(dis) { }
    24     bool operator < (const StrDis &tmp) const
    25     {
    26         return dis > tmp.dis;
    27     }
    28 };
    29 
    30 vector<Node> G[_N];
    31 priority_queue<StrDis> Q;
    32 LL Dis[_N], A[70000], A_cnt, N, T;
    33 
    34 void Dijkstra(LL Beg)
    35 {
    36     for (LL i = 1; i <= T+1; ++i) Dis[i] = INF;
    37     while (!Q.empty()) Q.pop();
    38     Dis[Beg] = 0;
    39     Q.push(StrDis(Beg, Dis[Beg]));
    40     while (!Q.empty()) {
    41         StrDis p = Q.top(); Q.pop();
    42         if (p.dis != Dis[p.v]) continue;
    43         vector<Node>::iterator it;
    44         for (it = G[p.v].begin(); it != G[p.v].end(); ++it)
    45             if (Dis[it->v] > Dis[p.v] + it->w) {
    46                 Dis[it->v] = Dis[p.v] + it->w;
    47                 Q.push(StrDis(it->v, Dis[it->v]));
    48             }
    49     }
    50     return;
    51 }
    52 
    53 int main()
    54 {
    55     scanf("%lld%lld", &N, &T);
    56     while (N--) {
    57         LL t1, t2;
    58         scanf("%lld%lld", &t1, &t2), ++t2;
    59         if (t2 <= t1) continue;
    60         A[++A_cnt] = t1, A[++A_cnt] = t2;
    61         G[t1].push_back(Node(t2, 1));
    62     }
    63     sort(A+1, A+1+A_cnt);
    64     for (LL i = 2; i <= A_cnt; ++i)
    65         if (A[i] != A[i-1]) G[A[i]].push_back(Node(A[i-1], 0));
    66     Dijkstra(1);
    67     if (Dis[T+1] == INF)
    68         printf("-1
    ");
    69     else
    70         printf("%lld
    ", Dis[T+1]);
    71     return 0;
    72 }
    C
      1 #include <stdio.h>
      2 #include <vector>
      3 #include <queue>
      4 #include <algorithm>
      5 
      6 using namespace std;
      7 
      8 const int _N = 1200;
      9 const int _M = 12000;
     10 
     11 typedef long long LL;
     12 
     13 const long long INF = 99999999999999LL;
     14 
     15 struct Node {
     16     LL v, w;
     17     Node(LL v, LL w):
     18         v(v), w(w) { }
     19 };
     20 
     21 struct StrDis {
     22     LL v, dis;
     23     StrDis(LL v, LL dis):
     24         v(v), dis(dis) { }
     25     bool operator < (const StrDis &tmp) const
     26     {
     27         return dis > tmp.dis;
     28     }
     29 };
     30 
     31 vector<Node> G[_N];
     32 priority_queue<StrDis> Q;
     33 
     34 LL Dis[_N], Extra[_N], N, M, K, MaxLen;
     35 LL t1[_M], t2[_M], t3[_M];
     36 
     37 void diudiu_Dijkstra(LL Beg)
     38 {
     39     for (LL i = 1; i <= N; ++i) Dis[i] = INF;
     40     while (!Q.empty()) Q.pop();
     41     Dis[Beg] = 0;
     42     Q.push(StrDis(Beg, Dis[Beg]));
     43     while (!Q.empty()) {
     44         StrDis p = Q.top(); Q.pop();
     45         if (p.dis != Dis[p.v]) continue;
     46         vector<Node>::iterator it;
     47         for (it = G[p.v].begin(); it != G[p.v].end(); ++it)
     48             if (Dis[it->v] > Dis[p.v] + it->w) {
     49                 Dis[it->v] = Dis[p.v] + it->w;
     50                 Q.push(StrDis(it->v, Dis[it->v]));
     51             }
     52     }
     53     return;
     54 }
     55 
     56 inline void Ins(LL t1, LL t2, LL t3) { G[t1].push_back(Node(t2, t3)); G[t2].push_back(Node(t1, t3)); return; }
     57 
     58 bool Check(LL lim)
     59 {
     60     int i;
     61     for (i = 1; i <= N; ++i) G[i].clear();
     62     for (i = 1; i <= M; ++i) {
     63         if (t1[i] == t2[i]) continue;
     64         Ins(t1[i], t2[i], t3[i] > lim);
     65     }
     66     diudiu_Dijkstra(1);
     67     return Dis[N] <= K;
     68 }
     69 
     70 int main()
     71 {
     72     LL i;
     73     scanf("%lld%lld%lld", &N, &M, &K);
     74     for (i = 1; i <= M; ++i) {
     75         scanf("%lld%lld%lld", &t1[i], &t2[i], &t3[i]);
     76         if (t1[i] == t2[i]) continue;
     77         Ins(t1[i], t2[i], 1);
     78         MaxLen = max(MaxLen, t3[i]);
     79     }
     80     
     81     diudiu_Dijkstra(1);
     82     if (Dis[N] == INF) { printf("-1
    "); return 0; }
     83     if (Dis[N] <= K) { printf("0
    "); return 0; }
     84     
     85     for (i = 1; i <= N; ++i) G[i].clear();
     86     for (i = 1; i <= M; ++i) {
     87         if (t1[i] == t2[i]) continue;
     88         Ins(t1[i], t2[i], t3[i]);
     89     }
     90     
     91     LL l = 1, r = MaxLen;
     92     while (l <= r) {
     93         LL mid = l+r >> 1;
     94         if (Check(mid)) r = mid-1;
     95         else l = mid+1;
     96     }
     97     
     98     printf("%lld
    ", l);
     99     return 0;
    100 }
    D

    题目:

    A通讯靠吼
    时间限制 : 10000 MS 空间限制 : 65536 KB
    问题描述
    亚马逊河流域部落的人们过着非常原始的生活,他们的通讯方式基本靠吼。何老板发现他们传消息的方式非常有意思,可以称为“吼叫传递”。比如A要传话给远处的D说"我稀饭你",A会对着B大吼"我稀饭D",接着B会对着C大吼"A稀饭D",C又会对着D大吼"A稀饭你"。就这样,一个传一个,消息就传了出去。但是,如果两人之间有障碍阻隔(比如一座山、一片树林)消息就无法传递过去了。每个人的嗓音大小不同,所以喊话的声能够传递的距离也可能不同。
    何老板今天访问的部落有n个原始人,何老板将它们编号1到n,白天,它们分布在雨林的各个地方进行劳作。何老板事先告诉你哪些人之间没有障碍物间隔,可以直接喊话。
    假设每个人都不会移动位置。何老板提问说出两个人的编号x和y,你能否告诉他x要传话到y,最少几个人要吼?

    输入格式
    第一行,三个整数n,m,q。n表示共n个原始人,m表示有m对人之间无障碍阻隔,q表示何老板提问的个数。
    第二行,n个空格间隔的整数,分别表示编号1到n的人每个人喊话声最远能传递的距离(<=5000)
    接下来m行,每行三个整数x,y,z 表示编号x和编号y的人之间无障碍阻隔,他们的直线距离为z(<=5000)
    接下来q行,每行两个整数x,y表示何老板想知道x传话到y最少需要几个人吼(x可能等于y)

    输出格式
    共q行,表示对何老板提问的回答。
    对于每个提问,如果x能传话到y,输出一个整数,表示最少需要吼叫的人数。如果不能,输出"no way"

    样例输入 1
    6 9 3
    9 10 7 8 6 3
    1 2 8
    2 3 9
    1 5 7
    5 2 16
    4 3 3
    3 6 8
    5 6 6
    4 6 5
    1 4 5
    1 3
    6 2
    2 6

    样例输出 1
    2
    no way
    3

    样例输入 2
    8 12 5
    14 7 30 18 33 7 8 6
    2 7 8
    2 6 6
    3 4 10
    4 7 10
    5 8 9
    8 5 13
    3 7 6
    3 6 3
    2 8 6
    5 2 7
    3 7 10
    6 3 12
    4 5
    1 8
    3 4
    2 3
    7 3

    样例输出 2
    3
    no way
    1
    2
    1

    提示
    n<=200 m<=10000 q<=1000

    B虫洞
    时间限制 : 10000 MS 空间限制 : 65536 KB
    问题描述
    农民约翰在巡查他的农场的时候发现了一些惊人的“虫洞”(“虫洞”的详情请参阅按因斯坦的解释)。虫洞非常奇特,它是一个单向通道,可以在瞬间把你传送到通道的另外一端,到达以后你会发现当前时间比你进洞时间要早(简单地说就是穿越了,回到了过去)。约翰的农场共有N块田,编号1到N,田与田之间共有M条小路相连(两块田间可能有多条小路相连)。约翰在这些田上总共找到了W个虫洞。
    约翰是个穿越爱好者,他想做下面这些事:以某块田为起点出发,穿过一些小路和虫洞,然后回到起点,使他回到起点时的时间早于他出发的时间,也许这样他就能在起点上见到另一个他自己了。
    为了帮助约翰知道他的方案能否可行,他会给你整个农场的地图。走过一条小路的耗时不会超过10000秒。一个虫洞一次最多能使时间倒退10000秒。

    输入格式
    第一行一个整数F,表示有F组测试数据。
    对于每组测试数据:
    第1行有三个整数N,M和W
    接下来M行,每行三个空格间隔的整数S,E,T分别表示一条小路的起点,终点和通过所需时间。
    接下来W行,每行三个空格间隔的整数S,E,T分别表示一个虫洞穿越的起点,终点和让时间倒退的秒数。

    输出格式
    包括F行,每行一个单词。"YES"表示约翰能成功。"NO"表示不能。

    样例输入 1
    2
    3 3 1
    1 2 2
    1 3 4
    2 3 1
    3 1 3
    3 2 1
    1 2 3
    2 3 4
    3 1 8

    样例输出 1
    NO
    YES

    样例输入 2
    5
    5 10 2
    1 3 277
    3 5 7116
    5 5 3567
    2 4 6023
    5 3 1453
    3 1 1083
    4 1 2414
    1 3 8174
    2 5 6055
    3 2 9029
    3 5 1466
    2 5 88
    5 10 2
    2 4 8688
    3 2 619
    3 5 9103
    5 5 6657
    5 3 8188
    3 3 7513
    5 1 9068
    1 3 5184
    4 5 8318
    4 3 3706
    5 3 591
    5 2 1605
    5 10 2
    4 3 7819
    3 1 4797
    4 3 6176
    1 3 6207
    2 1 9643
    3 1 2436
    2 5 2302
    3 5 401
    4 2 3435
    2 2 4987
    5 3 1173
    3 4 1078
    5 10 2
    1 5 9720
    5 2 7917
    1 5 5038
    2 4 6890
    3 5 9688
    1 5 1063
    1 3 5468
    5 2 5244
    2 2 435
    1 5 5763
    5 4 293
    1 2 929
    5 10 2
    4 3 66
    4 4 8651
    3 4 8304
    4 5 7845
    2 3 2923
    1 3 5425
    1 1 526
    5 4 2853
    1 3 4244
    5 3 6174
    2 5 1090
    1 4 103

    样例输出 2
    YES
    NO
    YES
    NO
    NO

    提示
    【数据范围】
    1<=N<=500
    1<=M<=2500
    1<=W<=200
    1<=F<=5

    C刷题
    时间限制 : - MS 空间限制 : 165536 KB
    评测说明 : 2s
    问题描述
    寒假里,何老板安排信竞班的N名学生去NKOJ刷题。
    寒假总共有T分钟,何老板要求每一分钟都至少有一个同学在刷题。这样的要求,让同学们很是恼火。
    每个学生只愿抽出一段特定时间刷题,比如第i个学生只愿意在[Si,Ei]这个时间段刷题。
    假期里大家都想玩,于是同学们想计算出最少需要安排多少个同学刷题就能满足要求。如果无解输出-1.

    输入格式
    第1行:两个整数N和T.

    接下来N行,每行两个整数表示一个学生刷题的时间段[Si,Ei]

    输出格式
    最少安排刷题的学生数.

    样例输入 1
    3 10
    1 7
    3 6
    6 10

    样例输出 1
    2

    样例输入 2
    3 10
    1 3
    4 7
    8 10

    样例输出 2
    3

    样例输入 3
    7 1000000
    1 100000
    99999 100001
    100000 200000
    200000 500000
    210000 490000
    499992 799987
    799988 1000000

    样例输出 3
    5

    提示
    1≤T≤1000000
    1≤N≤25000
    1≤Si≤Ei≤T
    样例1说明
    假期总共10分钟,安排学生1和学生3参与刷题即可保证每分钟都至少有一个同学在刷题.

    D架电话线
    时间限制 : 10000 MS 空间限制 : 65536 KB
    问题描述
    Farmer John打算将电话线引到自己的农场,但电信公司并不打算为他提供免费服务。于是,FJ必须为此向电信公司支付一定的费用。
    FJ的农场周围分布着N根按1..N顺次编号的废弃的电话线杆,任意两根电话线杆间都没有电话线相连。一共P对电话线杆间可以拉电话线,其余的那些由于隔得太远而无法被连接。
    第i对电话线杆的两个端点分别为A_i、B_i,它们间的距离为L_i 。数据中保证每对{A_i,B_i}最多只出现1次。编号为1的电话线杆已经接入了全国的电话网络,整个农场的电话线全都连到了编号为N的电话线杆上。也就是说,FJ的任务仅仅是找一条将1号和N号电话线杆连起来的路径,其余的电话线杆并不一定要连入电话网络。
    经过谈判,电信公司最终同意免费为FJ连结K对由FJ指定的电话线杆。对于此外的那些电话线,FJ需要为它们付的费用,等于其中最长的电话线的长度(每根电话线仅连结一对电话线杆)。如果需要连结的电话线杆不超过K对,那么FJ的总支出为0。
    请你计算一下,FJ最少需要在电话线上花多少钱。

    输入格式
    第一行输入3个用空格隔开的整数:N、P、以及K
    以下P行中,第i行为3个用空格隔开的整数:A_i、B_i、L_i。

    输出格式
    输出一个整数,为FJ在这项工程上的最小支出。
    如果任务不可能完成,输出-1。

    样例输入 1
    5 7 1
    1 2 5
    3 1 4
    2 4 8
    3 2 3
    5 2 9
    3 4 7
    4 5 6

    样例输出 1
    4

    样例输入 2
    4 5 0
    1 4 8
    2 4 2
    2 1 5
    3 1 9
    3 2 9

    样例输出 2
    5

    样例输入 3
    8 20 3
    3 6 14
    2 4 12
    6 5 15
    7 8 9
    2 6 9
    3 5 6
    2 1 14
    6 4 1
    5 8 2
    4 5 13
    8 6 5
    7 5 1
    4 8 2
    7 3 10
    6 7 1
    7 4 10
    2 8 9
    7 1 13
    5 1 6
    5 2 3

    样例输出 3
    0

    提示
    (1<=N<=1,000)
    (1<=P<=10,000)
    (1<=L_i<=1,000,000)
    (0<=K<N)

    样例1说明
    FJ选择如下的连结方案:1->3、3->2、2->5,这3对电话线杆间需要的电话线的长度分别为4、3、9。FJ让电信公司提供那条长度为9的电话线,于是,他所需要购买的电话线的最大长度为4。

  • 相关阅读:
    小a和uim之大逃离(dp)
    c++stl应用入门
    tar: 从成员名中删除开头的“/”
    yii中rights安装
    python中operator.itemgetter
    python中时间和时区
    python --那些你应该知道的知识点
    rsync拉取远程文件
    django中时区设置
    django中添加用户
  • 原文地址:https://www.cnblogs.com/ghcred/p/8684848.html
Copyright © 2020-2023  润新知