NOIP考前练习基础题想法记录
作为一名来自弱省的蒟蒻,面对即将到来的NOIP,唯一能做的就是祈祷(划去),就是刷题,本蒟蒻的愿望就是争取T1T2不丢分,T3T4就听天由命看人品了(rp++)。刷了一些前几年的题目,感觉前两道题的一些其实是存在一些解题想法的,本蒟蒻就想记录一下这段时间自己的心得。
- https://www.luogu.com.cn/problem/CF23B
这道题一眼瞅过去我其实是有点蒙的(甚至题目都有点没读懂),读了几次后明白了就是从度数为0的点开始删去这个点,同时将连着这个点的边上的另一个点的度数减一,并且下次删去度数为1再减连接的度数,并这么延续到n-1为止。这么听起来还是很抽象,那么我们便从少开始列举,首先我选择从n = 4开始分析,上图。!(请原谅我粗糙的画工)
那么我们想想怎样才能让尽可能多的人不被点到,首先我们如果将所有的点都连在一起。
(能用上cs了就是爽)
此时很明显所有人的朋友数都是3,全部会被点走,那么我们如果将任意一个关系去掉的话,那么这两个人就会因为彼此不是朋友了,朋友数目减少了一个,而其余的2个人仍然是原先的朋友数目,这里面我们假设将1和4之间的朋友关系去掉。
那么我们会发现1和4的朋友数为2,2和3的朋友数仍然为3,那么当去掉朋友数为2的人时,1和4便离开,2和3因为和1、4都是朋友,朋友数变成了1,所以此时的最大值即为2。我们便会发现,如果将所有的人排成一排,两边的两个人都不跟对方相连,而中间的其他人与非自己的所有人相连,那么此时只会让两边的两个人离开,而中间剩下的人数既为剩余的最大人数。在这里我画一个n = 6时的情景。
(强迫症状患者表示很淦)
我们发现这个结论是成立的,并且可以推广到之后的人数。但是需要注意的是,如果人数为1或2时,此时一定不会剩下任何一个人,那么我们便可以得出。
\[ ans=\left\{
\begin{aligned}
0, 0 \leq n \leqslant 2 \\
n - 2, n \geq 2
\end{aligned}
\right.
\]
那么接下来,皆大欢喜的上代码。
Code(点击打开)
#include
using namespace std;
int n,t;
int main(){
cin >> t;
while(t--){
cin >> n;
if(n == 1) cout << 0 << endl;
else if(n == 2) cout << 0 << endl;
else cout << n - 2 << endl;
}
return 0;
}
Code
#include
#include
using namespace std;
int n,m,a[10010];
long long ans;
int main(){
cin >> n >> m;
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1; i <= m; i++){
int x,y; cin >> x >> y;
ans += min(a[x], a[y]);
}
cout << ans << endl;
return 0;
}
Code
#include
#include
define ll long long
using namespace std;
int cnt,head[100010];
ll ans = 0,len = -1,n;
struct edge{
int to,next,dis;
}edge[100010 << 1];
void add(int x, int y, int t){
edge[++cnt].to = y;
edge[cnt].next = head[x];
edge[cnt].dis = t;
head[x] = cnt;
}
void dfs(int x, int y, ll now){
len=max(len, now);
for(int i = head[x]; i; i = edge[i].next){
int v = edge[i].to,d = edge[i].dis;
if(v == y) continue;
dfs(v, x, now + d);
}
return ;
}
int main(){
cin >> n;
for(int i = 1; i <= n - 1; i++){
int x,y,w; cin >> x >> y >> w;
add(x, y, w); add(y, x, w);
ans += w;
}
ans *= 2;
dfs(1, 0, 0);
cout << ans - len << endl;
return 0;
}
I'm noting without you.