A题,水题,但是因为我自己的写法没特判n是1导致WA了一次。
B题,直接用数组记录一下各个字母出现的次数即可,问号另外统计,然后每26个看看是否可行,如果可行那么其他的问号随便放就好。用map记录WA了一次,因为map里只要一个节点被用来记录过,然后被减到0,使用size()访问也会把这个节点计算在内的,需谨记。
C题,假设等级i时起始的数是a[i],由题意它是i的倍数。假设需要增加的数为ans[i],那么,a[i]+ans[i]*i=a[i+1]*a[i+1]。左边都是i的倍数,因此右边也一定是i的倍数,所以,a[i+1]同时是i+1和i的倍数。那么我们直接构造a[i+1]=i*(i+1),即a[i]=i*(i-1)即可。当然i=1的时候需要特判,是2(题目规定)。然后就很好求ans[i]了。
D题,好题。题意是给出一个图,和若干的边,其中权值为0的边是待定的边,问是否能够修改这些所有待定的边的权值(都变为一个正整数),使得s到t的最短路恰好为L。注意这题点的个数为n,因此可以考虑暴力的方法的。首先,不考虑这些待定的边,做s到t的最短路,得D,如果D小于L,显然答案是不可能的,如果等于L,那么待定的边都变为inf即可。否则,开始暴力。拿出所有的待定的边,让其权值变为1,再做s到t的最短路,如果新的D不比L大,那么这条边的权值再加上L-D即可(其他的待定边都变为inf)。如果所有的待定边都考虑了,仍不能完成实现上面的结果,那么答案就是不可能的。代码如下:

1 #include <stdio.h>
2 #include <algorithm>
3 #include <string.h>
4 #include <iostream>
5 #include <set>
6 #include <map>
7 #include <vector>
8 #include <queue>
9 using namespace std;
10 const int N = 1000 + 5;
11 typedef long long ll;
12 const ll inf = 1e18-100;
13 typedef pair<ll,int> pii;
14
15 int n,m,L,s,t;
16 struct edge
17 {
18 int u,v;
19 ll w;
20 };
21 vector<edge> G[N];
22 vector<edge> need,for_print;
23 void addEdge(int u,int v,ll w)
24 {
25 if(w == 0) need.push_back((edge){u,v,w});
26 else
27 {
28 G[u].push_back((edge){u,v,w});
29 G[v].push_back((edge){v,u,w});
30 for_print.push_back((edge){u,v,w});
31 }
32 }
33 ll dis[N];
34 ll dij()
35 {
36 for(int i=0;i<n;i++) dis[i] = i == s ? 0 : inf;
37 priority_queue<pii,vector<pii>,greater<pii> > Q;
38 Q.push(pii(0,s));
39 while(!Q.empty())
40 {
41 pii x = Q.top();Q.pop();
42 ll d = x.first;
43 int u = x.second;
44 if(dis[u] < d) continue;
45 for(int i=0;i<G[u].size();i++)
46 {
47 edge &e = G[u][i];
48 int v = e.v;
49 ll w = e.w;
50 if(dis[v] > dis[u] + w)
51 {
52 dis[v] = dis[u] + w;
53 Q.push(pii(dis[v], v));
54 }
55 }
56 }
57 return dis[t];
58 }
59
60 int main()
61 {
62 cin >> n >> m >> L >> s >> t;
63 for(int i=1;i<=m;i++)
64 {
65 int u,v,w;
66 scanf("%d%d%d",&u,&v,&w);
67 addEdge(u,v,w);
68 }
69 ll D = dij();
70 if(D < L) puts("NO");
71 else if(D == L)
72 {
73 puts("YES");
74 for(int i=0;i<for_print.size();i++) printf("%d %d %I64d\n",for_print[i].u,for_print[i].v,for_print[i].w);
75 for(int i=0;i<need.size();i++) printf("%d %d %I64d\n",need[i].u,need[i].v,inf);
76 }
77 else
78 {
79 int flag = 0;
80 for(int i=0;i<need.size()&&flag==0;i++)
81 {
82 edge &e = need[i];
83 e.w = 1;
84 int u = e.u, v = e.v;
85 ll w = e.w;
86 G[u].push_back((edge){u,v,w});
87 G[v].push_back((edge){v,u,w});
88 ll D = dij();
89 if(D <= L)
90 {
91 flag = 1;
92 e.w += L - D;
93 break;
94 }
95 }
96 if(flag == 0) puts("NO");
97 else
98 {
99 puts("YES");
100 for(int i=0;i<for_print.size();i++) printf("%d %d %I64d\n",for_print[i].u,for_print[i].v,for_print[i].w);
101 for(int i=0;i<need.size();i++)
102 {
103 if(need[i].w == 0) need[i].w = inf;
104 printf("%d %d %I64d\n",need[i].u,need[i].v,need[i].w);
105 }
106 }
107 }
108 return 0;
109 }
E题,据说是树分治,但是现在不会这个算法。明天再补。
来源:https://www.cnblogs.com/zzyDS/p/6354510.html
