2024年天梯成信校赛--L2-3,L2-4补题

L2-3:Gwen的小剪刀

题意:

思路:二分美感度+克鲁斯卡尔

int n,m,sum0;
typedef struct myp{
    int u,v;
    int b,h;
};
bool cmp(myp a,myp b){
    return a.h<b.h;
}
myp arr[200005];
int fa[100005];
int find(int x){
//	if(x==fa[x]) return x;
//	return fa[x]=find(fa[x]);
    if(x!=fa[x]) fa[x]=find(fa[x]);
    return fa[x];
}
void Union(int x,int y){
    int fa1=find(x),fa2=find(y);
    fa[fa1]=fa2;
}
bool check(int x){
    sum0=0;
    for(int i=1;i<=n;i++) fa[i]=i;
    int cnt=1;
    for(int i=1;i<=m;i++){
        if(arr[i].b>=x&&find(arr[i].u)!=find(arr[i].v)){
            Union(arr[i].u,arr[i].v);
            sum0+=arr[i].h;
            cnt++;
        }
    }
    if(cnt==n) return true;
    else return false;
}
void solve(){           //补l2-3 Gwen的小剪刀--二分+最小生成树
    cin>>n>>m;
    for(int i=1;i<=m;i++) cin>>arr[i].u>>arr[i].v>>arr[i].b>>arr[i].h;
    //sort(arr+1,arr+n+1,cmp);  //??????????逆天
    sort(arr+1,arr+m+1,cmp);
    int ans1=1,ans2=INT_MAX;
    int l=1,r=1e9+1;            //二分美观度
    while(l<=r){
        int mid=(l+r)/2;
        if(check(mid)){
            ans1=max(ans1,mid);
            ans2=sum0;   //!!!!!不能取ans2=min(ans2,sum0)!!!!!!!
            l=mid+1;
        }
        else r=mid-1;
    }
    cout<<ans1<<endl<<ans2;
}

ps:逆天排序范围写错了。。还有ans2-快乐值是不能取min的,在美感度x合法的情况下,算出来的即是最小的ans2。否则取了min会导致ans2对应的美感度不对。

 L2-4:超时空之恋

题意:

思路:通过某一条时空x的路到达的某一个点z.到达v点的时空必然是x。但是去v的点u可能存在三种时空的状态,那么到达v点的dis的最小代价,就是u点三种时空状态到达v点的最小值。即使u点在某个时空的距离是inf,也不影响。

//0-现代  1-古代  2-未来
const int inf=0x3f3f3f3f;
int n,m,k,ans=1e18;
//ans>=1e10&&ans<=1e18都是可以的...ans不能取inf,INT_MAX,LONG_LONG_MAX要么太小,要么太大。我也不知道具体为什么。。。一个一个试出来的。。
//还有..我的代码特例(n==1)好像跑不出来,但是提交可以过我就没有管了。
//代码思路上是没问题的,实现写的也没大问题(有小毛病,但是能发现并更正)..最最主要是ans的取值,一开始ans的取值能到24分,取小了只有18分。取得适当才能25分。。
vector<pair<int,pair<int,int>>> vct[100005];   //{ 时空,{ 到达点,代价 } }
priority_queue<pair<int,int>> pq;   //{ 距离,城镇点}
int vis[100005],dis[3][100005];
void dijkstra(int s){
    memset(vis,0,sizeof(vis));
    memset(dis,inf,sizeof(dis));
    dis[0][s]=0,dis[1][s]=k,dis[2][s]=k;     //dis[1][s]=k,dis[2][s]=k!!!
    pq.push({0,1});
    while(pq.size()){
        int from=pq.top().second;
        pq.pop();
        if(vis[from]) continue;
        vis[from]=1;
        for(auto v:vct[from]){
            int to=v.second.first,weight=v.second.second;
            if(v.first==0){
                if(dis[0][to]>dis[0][from]+weight){
                    dis[0][to]=dis[0][from]+weight;
                    pq.push({-dis[0][to],to});
                }
                if(dis[0][to]>dis[1][from]+weight+k){
                    dis[0][to]=dis[1][from]+weight+k;
                    pq.push({-dis[0][to],to});
                }
                if(dis[0][to]>dis[2][from]+weight+k){
                    dis[0][to]=dis[2][from]+weight+k;
                    pq.push({-dis[0][to],to});
                }
            }
            else if(v.first==1){
                if(dis[1][to]>dis[0][from]+weight+k){
                    dis[1][to]=dis[0][from]+weight+k;
                    pq.push({-dis[1][to],to});
                }
                if(dis[1][to]>dis[1][from]+weight){
                    dis[1][to]=dis[1][from]+weight;
                    pq.push({-dis[1][to],to});
                }
                if(dis[1][to]>dis[2][from]+weight+2*k){
                    dis[1][to]=dis[2][from]+weight+2*k;
                    pq.push({-dis[1][to],to});
                }
            }
            else if(v.first==2){
                if(dis[2][to]>dis[0][from]+weight+k){
                    dis[2][to]=dis[0][from]+weight+k;
                    pq.push({-dis[2][to],to});
                }
                if(dis[2][to]>dis[1][from]+weight+2*k){
                    dis[2][to]=dis[1][from]+weight+2*k;
                    pq.push({-dis[2][to],to});
                }
                if(dis[2][to]>dis[2][from]+weight){
                    dis[2][to]=dis[2][from]+weight;
                    pq.push({-dis[2][to],to});
                }
            }
        }
    }
}
void solve(){       //补L2-4 超时空之恋
    cin>>n>>m>>k;
    for(int i=1;i<=m;i++){
        int typ,u,v,w;
        cin>>typ>>u>>v>>w;
        vct[u].push_back({typ,{v,w}});
        vct[v].push_back({typ,{u,w}});
    }
    int tt; cin>>tt;
    vector<pair<int,int>> dungeon(tt);
    for(int i=0;i<tt;i++){
        int town,time; cin>>town>>time;
        dungeon[i].first=time,dungeon[i].second=town;
    }
    sort(dungeon.begin(),dungeon.end());   //按先出现的排
    dijkstra(1);
    int lasttown=0,lasttime=0;
    for(int i=0;i<dungeon.size();i++){
        if(i==dungeon.size()-1){
            if(dis[0][dungeon[i].second]>=dungeon[i].first) ans=min(ans,dis[0][dungeon[i].second]);
            if(dis[0][dungeon[i].second]<dungeon[i].first) ans=min(ans,lasttime);
            if(dis[1][dungeon[i].second]+k>=dungeon[i].first) ans=min(ans,dis[1][dungeon[i].second]+k);
            if(dis[1][dungeon[i].second]+k<dungeon[i].first) ans=min(ans,lasttime);
            if(dis[2][dungeon[i].second]+k>=dungeon[i].first) ans=min(ans,dis[2][dungeon[i].second]+k);
            if(dis[2][dungeon[i].second]+k<dungeon[i].first) ans=min(ans,lasttime);
        }
        else if(i>0){
            if(dis[0][lasttown]>=lasttime&&dis[0][lasttown]<dungeon[i].first) ans=min(ans,dis[0][lasttown]);
            if(dis[0][lasttown]<lasttime) ans=min(ans,lasttime);
            if(dis[1][lasttown]+k>=lasttime&&dis[1][lasttown]+k<dungeon[i].first) ans=min(ans,dis[1][lasttown]+k);
            if(dis[1][lasttown]+k<lasttime) ans=min(ans,lasttime);
            if(dis[2][lasttown]+k>=lasttime&&dis[2][lasttown]+k<dungeon[i].first) ans=min(ans,dis[2][lasttown]+k);
            if(dis[2][lasttown]+k<lasttime) ans=min(ans,lasttime);
        }
        lasttime=dungeon[i].first;
        lasttown=dungeon[i].second;
    }
    //ans不够大可能取不到,lasttime的1e18。ans太大的话inf会一定被取到./.
    if(ans!=1e18/*&&ans!=inf&&ans!=inf+k&&ans!=inf+2*k*/) cout<<ans;
    else cout<<"-1";
}

ps:这题要注意ans的初始取值..以及dis[0][s]=0,dis[1][s]=k,dis[2][s]=k;

 

posted @ 2024-03-25 17:39  osir  阅读(19)  评论(0编辑  收藏  举报