4月训练补题
B - Destruction
最小生成树模板题,注意负权值的边不要加入。
#include<iostream> #include<algorithm> #include<string.h> #include<string> #include<map> #include<vector> #include<queue> #include<set> #include<math.h> using namespace std; typedef long long ll; typedef pair<ll,ll> pll; const ll N=2e5+5; map<pair<ll,ll>,int> mp; ll a[N];ll head[N]; ll sum;ll fa[N]; ll n,m; ll ans; struct ss{ ll x,y,w; }e[N]; ll find(ll x){ if(fa[x]==x) return x; return fa[x]=find(fa[x]); } int cmp(ss a,ss b){ return a.w<b.w; } void solve(){ for(ll i=1;i<=n;i++){ fa[i]=i; } sort(e+1,e+1+m,cmp); ll cnt=0; for(int i=1;i<=m;i++){ ll x=e[i].x; ll y=e[i].y; ll w=e[i].w; ll gx=find(x);ll gy=find(y); if(gx!=gy){ if(w>0) ans+=w; cnt++; fa[gy]=gx; if(cnt==n-1){ return ; } } } } signed main(){ cin>>n>>m; for(int i=1;i<=m;i++){ cin>>e[i].x>>e[i].y>>e[i].w; if(e[i].w>0) sum+=e[i].w; } solve(); cout<<sum-ans; } /*orz*/
C - Blocked Roads
题意:每次删除这条边之后,求1-n的最短距离,否则输出-1
思路:最短路,判断这条边在不在最短路的路径中,如果不在,就直接输出,否则就再跑一遍最短路。
#include<iostream> #include<algorithm> #include<string.h> #include<string> #include<map> #include<vector> #include<queue> #include<set> #include<math.h> using namespace std; typedef long long ll; typedef pair<ll,ll> pll; const ll N=2e5; const ll inf=0x3f3f3f3f; ll n,m,cnt; struct ss{ ll to;int next; }e[N]; ll head[N]; pair<ll,ll> q[N]; ll dis[N],vis[N]; ll fa[N]; set<pll> vd; void add(ll x,ll y){ e[++cnt].to=y; e[cnt].next=head[x]; head[x]=cnt; } void dij(ll x,ll y){ memset(vis,0,sizeof(vis)); fill(dis,dis+N,inf); dis[1]=0; priority_queue<pll,vector<pll>,greater<pll>> p; p.push({1,0}); while(p.size()){ pll t=p.top(); p.pop(); ll now=t.first;ll d=t.second; if(vis[now]) continue; vis[now]=1; for(int i=head[now];i;i=e[i].next){ ll ne=e[i].to; if(x==now&&ne==y) continue; if(dis[ne]>d+1){ dis[ne]=d+1; p.push({ne,d+1}); fa[ne]=now; } } } } signed main(){ cin>>n>>m; for(ll i=1;i<=m;i++){ ll x,y;cin>>x>>y; add(x,y); q[i]={x,y}; } dij(-1,-1); ll t=n; while(fa[t]){ vd.insert({fa[t],t}); t=fa[t]; }//最短路回溯记录路径 ll ans; if(dis[n]>=inf) ans=-1; else ans=dis[n]; for(ll i=1;i<=m;i++){ if(vd.count({q[i].first,q[i].second})){ dij(q[i].first,q[i].second); if(dis[n]>=inf) cout<<"-1"<<endl; else cout<<dis[n]<<endl; } else cout<<ans<<endl; } } /*orz*/
题意:每次两个选择,选1,从该点切割成两份,选2,判断该点所在的木块长度
思路:每一个切割的点,储存起来,然后二分查询,输出。
#include<iostream> #include<algorithm> #include<string.h> #include<string> #include<map> #include<vector> #include<queue> #include<set> #include<math.h> using namespace std; typedef long long ll; typedef pair<ll,ll> pll; const ll N=2005; map<pair<ll,ll>,int> mp; map<ll,int> ml; ll vis[N]; ll cnt; set<ll> q; signed main(){ ll n,m;cin>>n>>m; ll ans; q.insert(0); q.insert(n); for(int i=1;i<=m;i++){ ll c,x;cin>>c>>x; ans=0; if(c==1) q.insert(x); else{ ans=(*q.lower_bound(x)-*(--q.lower_bound(x))); cout<<ans<<endl; } } } /*orz*/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)