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;