NOIP模拟 17.9.28

公交车
【问题描述】
市内有??个路口和??条双向道路,每条道路都有过路费,第??条道路的过路费
为??%元。市内还有??条公交线路,公交车只在路口停靠,而且一路公交车只会沿
着固定的线路往返行驶。上第??路公交车需要??%元的费用,但费用是一次性的,
即你可以在公交线路上的任意停靠路口下车。但是一旦下车了,如果要再次上车,
则还需要再次付费。
现在你在路口??,你想知道从??出发到其它每个路口的最小费用是多少。
【输入格式】
输入的第一行包含四个整数??、??、??和??,分别代表路口数、道路数、公交
线路数和你所处的路口编号。
接下来的??行,每行包含三个整数??%、??%和??%,代表第??条道路连接??%路口和
??%路口,并且通过这条道路需要缴纳??%元的过路费。
接下来的??行,每行首先是两个整数??%和??%,代表第??路公交车的上车费用为??%
元,而且公交线路共有??%个停靠路口。接下来同一行内有??%个整数,按顺序给出
了这路公交车的各个停靠路口。
【输出格式】
输出一行,包含??个整数,为从路口??到每个路口的最小费用。
【样例】
transprt.in transprt.out
5 4 1 1
1 2 1
2 3 1
3 4 1
4 5 1
2 4 2 3 4 5
0 1 2 3 3
【样例解释】
到路口5 时需要先走到路口2 然后搭公交车,费用为1 + 2 = 3。
其他情况均不需要搭公交车。
【数据规模和约定】
对于30%的数据,?? ≤ 100,?? = 1。
对于另外30%的数据,?? = 0。
对于100%的数据,1 ≤ ?? ≤ 100000,1 ≤ ?? ≤ 200000,1 ≤ ?? ≤ 50000,
Σ??% ≤ 200000, 1 ≤ ??%, ??% ≤ 107。

【题解】

水最短路

公交车虚一个点,从经过的点往虚的点连有边权,虚的点往经过的点连边权0即可

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstdlib>
  4 #include <cstring>
  5 #include <algorithm>
  6 #include <queue>
  7 #include <vector>
  8
  9 inline void read(long long &x)
 10 {
 11     x = 0;char ch = getchar(), c = ch;
 12     while(ch < ‘0‘ || ch > ‘9‘) c = ch, ch = getchar();
 13     while(ch <= ‘9‘ && ch >= ‘0‘) x = x * 10 + ch - ‘0‘, ch = getchar();
 14     if(c == ‘-‘)x = -x;
 15 }
 16
 17 const long long INF = 0x3f3f3f3f;
 18 const long long MAXN = 300000 + 1000;
 19 const long long MAXM = 400000 + 1000;
 20 const long long MAXK = 70000 + 1000;
 21 const long long MAXT = 400000 + 1000;
 22
 23 //开longlong
 24
 25 long long n,m,k,s;
 26
 27 struct Edge
 28 {
 29     long long u,v,w,next;
 30     Edge(long long _u, long long _v, long long _w, long long _next){u = _u;v =_v;w = _w;next = _next;}
 31     Edge(){}
 32 } edge[MAXM * 2 + MAXT * 2];
 33 long long head[MAXN + MAXK], cnt;
 34
 35 inline void insert(long long a, long long b, long long c)
 36 {
 37     edge[++cnt] = Edge(a,b,c,head[a]);
 38     head[a] = cnt;
 39 }
 40
 41 struct Node
 42 {
 43     long long v,w;
 44     Node(long long _v, long long _w){v = _v;w = _w;}
 45     Node(){}
 46 };
 47 struct cmp
 48 {
 49     bool operator()(Node a, Node b)
 50     {
 51         return a.w > b.w;
 52     }
 53 };
 54 long long d[MAXN + MAXK], b[MAXN + MAXK];
 55 std::priority_queue<Node, std::vector<Node>, cmp> q;
 56
 57 void dijkstra()
 58 {
 59     memset(d, 0x3f, sizeof(d));
 60     d[s] = 0;
 61     q.push(Node(s, 0));
 62     Node now;long long v, u;
 63     while(q.size())
 64     {
 65         now = q.top(), q.pop();
 66         if(b[now.v])continue;
 67         u = now.v;
 68         b[u] = 1;
 69         for(register long long pos = head[u];pos;pos = edge[pos].next)
 70         {
 71             v = edge[pos].v;
 72             if(d[v] > d[u] + edge[pos].w)
 73             {
 74                 d[v] = d[u] + edge[pos].w;
 75                 q.push(Node(v, d[v]));
 76             }
 77         }
 78     }
 79 }
 80
 81 int main()
 82 {
 83     read(n), read(m), read(k), read(s);
 84     long long tmp1, tmp2, tmp3;
 85     for(register long long i = 1;i <= m;++ i)
 86     {
 87         read(tmp1), read(tmp2), read(tmp3);
 88         insert(tmp1, tmp2, tmp3);
 89         insert(tmp2, tmp1, tmp3);
 90     }
 91     for(register long long i = 1;i <= k;++ i)
 92     {
 93         read(tmp3);read(tmp1);
 94         for(register long long j = 1;j <= tmp1;++ j)
 95         {
 96             read(tmp2);
 97             insert(n + i, tmp2, 0);
 98             insert(tmp2, n + i, tmp3);
 99         }
100     }
101     dijkstra();
102     for(register long long i = 1;i <= n;++ i)
103         printf("%lld ", d[i]);
104     return 0;
105 }

T1

灌溉
【问题描述】
Farmer John 有??个牧场,他希望灌溉他的所有牧场。牧场编号为1 ∼ ??,要
灌溉一个牧场有两种方式,一个是直接在这个牧场建设一个小型水库,另一个是
从别的牧场向这个牧场引水。在第??个牧场建立小型水库需要??%美元,而从第?? 个
牧场向第??个牧场引水需要??%,<美元。即便牧场??没有建设小型水库,只要有别的有
水的水库向它引水,那它自己也有水,而且可以向别的水库引水。请告诉FJ 灌
溉所有牧场所需的最小代价。
【输入格式】
输入数据的第一行包含一个整数??,代表牧场的数目。
接下来??行,每行包含一个整数??%,代表建立小型水库的代价。
接下来??行,每行包含??个整数。第??行的第??个数为??%,<。
【输出格式】
输出一行,包含一个整数,即为答案。
【样例】
irrigate.in irrigate.out
4
5
4
4
3
0 2 2 2
2 0 3 3
2 3 0 4
2 3 4 0
9
【样例解释】
FJ 应该在第4 块牧场上建立小型水库,然后从这块牧场向其他所有牧场引
水。总费用为3 + 2 + 2 + 2 = 9美元。
【数据规模和约定】
对于20%的数据,?? ≤ 10。
对于40%的数据,?? ≤ 50。
对于60%的数据,?? ≤ 100。
对于100%的数据,1 ≤ ?? ≤ 300,1 ≤ ??%,<,??% ≤ 10>,??%,< = ??<,%,??%,% = 0。

【题解】

水MST

空间开小了,爆掉80

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <algorithm>
 6
 7 const long long INF = 0x3f3f3f3f;
 8 const long long MAXN = 300000 + 10;
 9 const long long MAXM = 1000000 + 1000;
10
11 inline void read(long long &x)
12 {
13     x = 0;char ch = getchar(), c = ch;
14     while(ch < ‘0‘ || ch > ‘9‘) c = ch, ch = getchar();
15     while(ch <= ‘9‘ && ch >= ‘0‘) x = x * 10 + ch - ‘0‘, ch = getchar();
16     if(c == ‘-‘)x = -x;
17 }
18
19 long long n, ans, rank[MAXN + MAXN], w[MAXM + MAXM], u[MAXM + MAXM], v[MAXM + MAXM], fa[MAXN + MAXN], cnt;
20
21 long long cmp(long long a, long long b)
22 {
23     return w[a] < w[b];
24 }
25
26 long long find(long long x)
27 {
28     return x == fa[x] ? x : fa[x] = find(fa[x]);
29 }
30
31 int main()
32 {
33     read(n);
34     for(register long long i = n * 10;i >= 1;-- i)fa[i] = i;
35     for(register long long i = 1;i <= n;++ i)
36         ++ cnt, u[cnt] = n + 1, v[cnt] = i, read(w[cnt]), rank[cnt] = cnt;
37
38     long long tmp,f1,f2;
39     for(register long long i = 1;i <= n;++ i)
40         for(register long long j = 1;j <= n;++ j)
41         {
42             read(tmp);
43             if(i >= j)continue;
44             ++cnt, u[cnt] = i, v[cnt] = j, w[cnt] = tmp;
45             rank[cnt] = cnt;
46         }
47     std::sort(rank + 1, rank + 1 + cnt, cmp);
48     for(register long long k = 1;k <= cnt;++ k)
49     {
50         f1 = find(u[rank[k]]), f2 = find(v[rank[k]]);
51         if(f1 == f2)continue;
52         fa[f1] = f2;
53         ans += w[rank[k]];
54     }
55     printf("%lld", ans);
56     return 0;
57 }

T2

对决
【问题描述】
有两个人在玩一个公平组合游戏。现在我们要分析这两个人谁能获胜。给定
这个游戏的所有局面和局面间的转移,显然它会构成一个DAG。
如果一个局面不能转移到其它局面,那么称这个局面为终止局面;如果一个
局面不能由其它局面转移而来,那么称这个局面为起始局面。
已知这个游戏有??个局面和??条转移(即DAG 有??个点和??条边),有唯一的
起始局面,但可能有多个终止局面。同时,每一个局面都可以由初始局面到达。
现在告诉你所有终止局面是哪方获胜,你能否求出每个局面是先手必胜态还是先
手必败态?
【输入格式】
输入数据的第一行包含两个正整数??和??,分别代表游戏的局面数和转移数。
接下来??行,每行两个整数??%和??%,代表第??条转移是由局面??%转移到局面??%。
接下来一行,有若干个整数,依次代表所有终止局面的获胜方,按照其节点
编号从小到大给出。如果数字为1,那么在该终止局面的先手获胜;如果数字为
0,则后手获胜。
【输出格式】
输出??行,每行包含一个字符串,第??行的字符串代表编号为??的局面的状态。
如果局面为先手必胜态,则输出“First”,否则输出“Last”(均不含引号)。
【样例】
duel.in duel.out
5 5
1 2
1 3
2 4
4 3
4 5
0 1
First
Last
Last
First
First
【样例解释】
局面3 和5 是终止局面,其中3 为后手胜,5 为先手胜。
根据博弈论的有关知识,不难得出答案。
【数据规模和约定】
对于30%的数据,1 ≤ ??,?? ≤ 10。
对于另外30%的数据,?? = ?? − 1。
对于100%的数据,1 ≤ ?? ≤ 100000,1 ≤ ?? ≤ 200000。
【提示】
对于没有接触过博弈论的同学,这里普及一点小常识。如果你之前了解博弈
论相关理论,可以忽略这一段文字。
我们用“局面”代指博弈论中游戏的一个状态。所谓“公平组合游戏”即不
存在随机性、双方信息相同、双方在面临同一局面时的选择也相同的游戏。
比如在本题的游戏中,游戏不存在随机性(游戏进程仅受双方的选择所影响),
双方了解游戏的所有信息(整个游戏的局面和转移),双方在面临同一局面时的
选择也相同(都只能选择从当前局面转移到的其他局面,这些局面被称为后继局
面)。
在一个公平组合游戏中,所有局面都可以分为“先手必胜”和“先手必败”
两种。其含义为,如果双方都以最优策略行动,那么面临这一局面的一方(即先
手) 将必胜或必败。
对于终止局面(即不存在后继局面,当一方到达这一局面时,游戏结束),
其为先手必胜还是先手必败是游戏定义的。在本题中,即为输入给定的。
而对于非终止局面,其为先手必胜还是先手必败是由其后继局面决定的:
• 如果存在一个后继局面为先手必败态,那么当前局面为先手必胜态。
因为先手可以从所有后继局面中任意选择,他当然会选择先手必败的
后继局面——面临这一后继局面的将是后手。
• 否则,即如果所有后继局面都是先手必胜态,那么当前局面为先手必
败态。
根据以上两条规则,可以判定游戏中所有局面的状态。

【题解】

水dfs。题解是top排序,但是容易被卡成有一定常数的kn^q,k < 1,可能会爆掉

我这个算法是稳稳地O(n),(n), Ω(n)

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <algorithm>
 6
 7 inline void read(int &x)
 8 {
 9     x = 0;char ch = getchar(), c = ch;
10     while(ch < ‘0‘ || ch > ‘9‘) c = ch, ch = getchar();
11     while(ch <= ‘9‘ && ch >= ‘0‘) x = x * 10 + ch - ‘0‘, ch = getchar();
12     if(c == ‘-‘)x = -x;
13 }
14
15 const int INF = 0x3f3f3f3f;
16 const int MAXN = 1000000 + 10;
17 const int MAXM = 2000000 + 10;
18
19 struct Edge
20 {
21     int u,v,next;
22     Edge(int _u, int _v, int _next){u = _u;v = _v;next = _next;}
23     Edge(){}
24 }edge[MAXM];
25
26 int chudu[MAXN], head[MAXN], rudu[MAXN], zhuangtai[MAXN], cnt, n, m, b[MAXN];
27
28 inline void insert(int a, int b)
29 {
30     edge[++cnt] = Edge(a,b,head[a]);
31     head[a] = cnt;
32 }
33
34 //1为必败态,2为必胜态
35
36 void dfs(int u)
37 {
38     int flag = 1;
39     for(register int pos = head[u];pos;pos = edge[pos].next)
40     {
41         int v = edge[pos].v;
42         if(b[v])
43         {
44             if(zhuangtai[v] == 1)
45                 flag = 2;
46         }
47         else
48         {
49             dfs(v);
50             if(zhuangtai[v] == 1)
51                 flag = 2;
52         }
53     }
54     zhuangtai[u] = flag;
55     b[u] = 1;
56 }
57
58 int main()
59 {
60     read(n), read(m);
61     int tmp1, tmp2;
62     for(register int i = 1;i <= m;++ i)
63     {
64         read(tmp1), read(tmp2);
65         insert(tmp1, tmp2);
66         ++ chudu[tmp1];
67         ++ rudu[tmp2];
68     }
69     for(register int i = 1;i <= n;++ i)
70         if(!chudu[i])
71             read(zhuangtai[i]), ++ zhuangtai[i], b[i] = 1;
72     for(register int i = 1;i <= n;++ i)
73         if(rudu[i] == 0 && !b[i])
74             dfs(i);
75     for(register int i = 1;i <= n;++i)
76     {
77         if(zhuangtai[i] == 2)
78             printf("First\n");
79         else
80             printf("Last\n");
81     }
82     return 0;
83 }

T3

时间: 2024-11-05 17:23:57

NOIP模拟 17.9.28的相关文章

NOIP模拟17.8.17

NOIP模拟17.8.17 A 小 G 的字符串文件名 输入文件 输出文件 时间限制 空间限制str.pas/c/cpp str.in str.out 1s 128MB[题目描述]有一天,小 L 给小 G 出了这样一道题:生成一个长度为 n 的.全由小写英文字母构成的字符串,只能使用 k 种字母.要求满足:• 字符串中相邻的两个字母不能相同.• 必须出现恰好 k 种不同的字母.这样的合法字符串可能有很多,小 L 让小 G 输出字典序最小的那个.小 G 太笨啦,不会做这道题,希望你帮帮他.[输入格

NOIP模拟 17.8.18

NOIP模拟17.8.18 A.小菜一碟的背包[题目描述]Blice和阿强巴是好朋友但萌萌哒Blice不擅长数学,所以阿强巴给了她一些奶牛做练习阿强巴有 n头奶牛,每头奶牛每天可以产一定量的奶,同时也需要一定量的草作为饲料对于第 i头奶牛来说,它每天可以产 vi升的奶,同时需要 wi千克的草作为饲料现在来自蚯蚓国的九条可怜想借一些奶牛,使借走的这些奶牛每天的总产奶量最大,但九条可怜很穷,每天最多只能提供W千克的草作为饲料,而且她还需要对付跳蚤国的神刀手,所以她把这个问题交给了阿强巴,不不不……阿

NOIP模拟17.9.21

NOIP模拟17.9.21 1 任务安排manage.in/.out/.cpp1.1 问题描述你有N 个工作,同一时刻只能做一个任务, 其中每个工作有其所需时间, 及完成的Deadline(截止时间), 问要完成所有工作, 最迟要从什么时候开始.你最早可以从时间0 开始工作.1.2 输入格式第一行一个整数N,表示任务数量接下来n 行,每行两个整数,Ti; Si,分别表示该任务的持续时间和截止时间.1.3 输出格式输出一个整数,表示最晚的开始时间,如果不能完成,输出-1.1.4 样例输入43 58

NOIP模拟17.9.22

NOIP模拟17.9.22 前进![问题描述]数轴的原点上有一只青蛙.青蛙要跳到数轴上≥ ??的位置去,但很不幸数轴上有??个区间是禁区,不能进入.青蛙会选择一个长度??,从原点开始每次向右跳长度为??的一段.一路上青蛙会停的位置是0, ??, 2??,…直到跳到了≥ ??的位置,任意一个位置都不能在禁区中.请求出??的最小值,注意??可以是实数.[输入格式]输入文件为susume.in.输入文件的第一行包含两个整数??和??,含义如问题描述中所述.接下来??行,每行描述一个禁区.每行有两个整数

NOIP模拟 17.8.16

A 债务文件名 输入文件 输出文件 时间限制 空间限制debt.pas/c/cpp debt.in debt.out 1s 128MB[题目描述]小 G 有一群好朋友,他们经常互相借钱.假如说有三个好朋友 A,B,C.A欠 B 20 元,B 欠 C 20 元,总债务规模为 20+20=40 元.小 G 是个追求简约的人,他觉得这样的债务太繁杂了.他认为,上面的债务可以完全等价为 A 欠 C 20 元,B 既不欠别人,别人也不欠他.这样总债务规模就压缩到了 20 元.现在给定 n 个人和 m 条债

NOIP模拟 6.28

NOIP模拟赛6.28 Problem 1 高级打字机(type.cpp/c/pas) [题目描述] 早苗入手了最新的高级打字机.最新款自然有着与以往不同的功能,那就是它具备撤销功能,厉害吧. 请为这种高级打字机设计一个程序,支持如下3种操作: 1.T x:在文章末尾打下一个小写字母x.(type操作) 2.U x:撤销最后的x次修改操作.(Undo操作) (注意Query操作并不算修改操作) 3.Q x:询问当前文章中第x个字母并输出.(Query操作) 文章一开始可以视为空串. [输入格式]

NOIP模拟赛 6.29

2017-6-29 NOIP模拟赛 Problem 1 机器人(robot.cpp/c/pas) [题目描述] 早苗入手了最新的Gundam模型.最新款自然有着与以往不同的功能,那就是它能够自动行走,厉害吧. 早苗的新模型可以按照输入的命令进行移动,命令包括‘E’.‘S’.‘W’.‘N’四种,分别对应东南西北.执行某个命令时,它会向对应方向移动一个单位.作为新型机器人,它可以执行命令串.对于输入的命令串,每一秒它会按命令行动一次.执行完命令串的最后一个命令后,会自动从头开始循环.在0时刻时机器人

liu_runda 给辣鸡蒟蒻做的 NOIP模拟赛 1.0 第二题 任(duty) 题解

问题 B: 任(duty) 时间限制: 2 Sec  内存限制: 512 MB 题目描述 liu_runda退役之后就失去梦想开始咸鱼生活了- Bilibili夏日画板活动中,所有人都可以在一块画板上进行像素画创作.UOJ群有一群无聊的人决定在画板上创作一个50*50的UOJ的LOGO.如下图. 这块画板实际上是很大的矩形网格.一个网格是一像素. 一个人每三分钟才能画一个像素.所以liu_runda的咸鱼生活非常无聊. 郭神表示他实在是看不下去liu_rudna这只颓狗了,于是随手出了一道神题,

noip模拟测试11

T1:string 第一眼秒出思路,这不就是排序那道题的加强版吗? 然而歪?解复杂度虽然是对的,但常数过大,竟被卡到70 歪?解:(实际上std写的就是这个,但据说std被卡掉了 OAO) 因为字符集很小,所以我们可以把区间排序改为区间查询和覆盖 即:先查询区间内所有字符的个数,再从左端点开始按照大小关系依次将长度为字符个数的区间修改为该字符. 期望复杂度O ( 26*mlogn ),实际复杂度O ( 26*mlogn*(巨大的常数) ) 所以需要一(feng)定(kuang)的卡常 正?解: