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*/
复制代码

E - Cutting Woods

题意:每次两个选择,选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*/
复制代码

 

posted @   HHzp  阅读(27)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示