小木乃伊到我家
/**
* dijkstra模板题
*/
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using std::cin;
using std::cout;
const int maxn=2e5+5;
const int maxm=4e5+5;
const int mod=1e9+7;
int head[maxn],to[maxm],ne[maxm],w[maxm],id;
void add(int x,int y,int z){
ne[++id]=head[x],head[x]=id,to[id]=y,w[id]=z;
ne[++id]=head[y],head[y]=id,to[id]=x,w[id]=z;
}
int n,m;
int d[maxn];
bool vis[maxn];
#define fi first
#define se second
#define pii std::pair<int,int>
bool dijkstra(){
for(int i=2;i<=n;i++)d[i]=1e18;
std::priority_queue<pii,std::vector<pii>,std::greater<pii>> que;
que.push({0,1});
while(!que.empty()){
pii p=que.top();que.pop();
if(vis[p.se])continue;
int i=p.se,cost1=p.fi;
vis[i]=1;
for(int e=head[i],id=to[e];e;e=ne[e],id=to[e]){
if(vis[id])continue;
int cost2=cost1+w[e];
if(cost2<d[id]){
d[id]=cost2;
que.push({cost2,id});
}
}
}
return vis[n];
}
void solve(){
cin>>n>>m;
for(int i=1;i<=m;i++){
int x,y,z;
cin>>x>>y>>z;
add(x,y,z);
}
cout<<(dijkstra()?std::to_string(d[n]):"qwb baka")<<endl;
}
signed main(){
// freopen("file.txt","r",stdin);
std::ios_base::sync_with_stdio(false);
std::cin.tie(nullptr),std::cout.tie(nullptr);
// cout<<std::fixed<<std::setprecision(15);
int tt=1;//cin>>tt;
while(tt--)solve();
return 0;
}
武
/**
* 简单题
* 题目中说了给定一个n-1条边的所有点都联通的图,本质上就是一棵树
* 那么问题就变成了给定一棵以p点为根的树,在p点到其他点的距离中,求第k小的值
* 既然是一棵树,那么树上任意两点的简单路径有且仅有一条,其距离是确定的
* 那么直接从p点开始bfs或者dfs整棵树求出d数组即可,代码给出了bfs和dfs的做法
*/
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using std::cin;
using std::cout;
const int maxn=1e6+5;
const int maxm=2e6+5;
const int mod=1e9+7;
int head[maxn],to[maxm],ne[maxm],w[maxn],id;
void add(int x,int y,int z){
ne[++id]=head[x],head[x]=id,to[id]=y,w[id]=z;
ne[++id]=head[y],head[y]=id,to[id]=x,w[id]=z;
}
int n,p,k;
int d[maxn];
bool vis[maxn];
void bfs(int s){
std::queue<int> que;
que.push(s);
vis[s]=true,d[s]=0;
while(!que.empty()){
int i=que.front();
que.pop();
for(int e=head[i],id=to[e];e;e=ne[e],id=to[e]){
if(vis[id])continue;
vis[id]=true;
d[id]=d[i]+w[e];
que.push(id);
}
}
}
void dfs(int i){
vis[i]=true;
for(int e=head[i],id=to[e];e;e=ne[e],id=to[e]){
if(vis[id])continue;
d[id]=d[i]+w[e];
dfs(id);
}
}
void solve(){
cin>>n>>p>>k;
for(int i=1;i<n;i++){
int x,y,z;
cin>>x>>y>>z;
add(x,y,z);
}
//bfs(p);
dfs(p);
k++;
//将d数组中第k小的值放在下标为k的位置
std::nth_element(d+1,d+k,d+1+n);
cout<<d[k]<<endl;
}
signed main(){
// freopen("file.txt","r",stdin);
std::ios_base::sync_with_stdio(false);
std::cin.tie(nullptr),std::cout.tie(nullptr);
// cout<<std::fixed<<std::setprecision(15);
int tt=1;//cin>>tt;
while(tt--)solve();
return 0;
}
旅行
/**
* dijkstra简单题
* 题目:给定一个无向图,求出(任意不同三点)x->y->z在走最短路线情况下的最大距离
* 遍历中间点y,对每个中间点跑dijkstra算法求y点到其他点的最短距离,
* 取距离中不为0且可以达到的最大的两个距离则为以y为中间点的最优解
* 答案即为所有中间点的最优解中的最大值
*/
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using std::cin;
using std::cout;
const int maxn=1e3+5;
const int maxm=2e3+5;
const int mod=1e9+7;
int head[maxn],to[maxm],ne[maxm],w[maxm],id;
void add(int x,int y,int z){
ne[++id]=head[x],head[x]=id,to[id]=y,w[id]=z;
ne[++id]=head[y],head[y]=id,to[id]=x,w[id]=z;
}
int n,m;
int d[maxn];
bool vis[maxn];
#define fi first
#define se second
#define pii std::pair<int,int>
void dijkstra(int s){
//初始化数据
for(int i=1;i<=n;i++)d[i]=1e18,vis[i]=false;
d[s]=0;
std::priority_queue<pii,std::vector<pii>,std::greater<pii>> que;
que.push({0,s});
while(!que.empty()){
int i=que.top().se,cost1=que.top().fi;
que.pop();
if(vis[i])continue;
vis[i]=true;
for(int e=head[i],id=to[e];e;e=ne[e],id=to[e]){
if(vis[id])continue;
int cost2=cost1+w[e];
if(d[id]>cost2){
d[id]=cost2;
que.push({d[id],id});
}
}
}
}
void solve(){
cin>>n>>m;
//多组样例输入,每次都必须初始化图
id=0;
for(int i=1;i<=n;i++)head[i]=0;
for(int i=1;i<=m;i++){
int x,y,z;
cin>>x>>y>>z;
add(x,y,z);
}
int ans=-1;
for(int i=1;i<=n;i++){
dijkstra(i);
std::sort(d+1,d+1+n);
int ed=n;
//距离为1e18的点为不可到达的点
while(d[ed]==1e18)ed--;
//d[1]必然等于0,因为i到i的距离为0.
//如果ed>=3,则代表至少有其他的两个点可以从i点到达,取最大的两个距离,即d[ed-1]和d[ed]
if(ed>=3)ans=std::max(ans,d[ed-1]+d[ed]);
}
cout<<ans<<endl;
}
signed main(){
// freopen("file.txt","r",stdin);
std::ios_base::sync_with_stdio(false);
std::cin.tie(nullptr),std::cout.tie(nullptr);
// cout<<std::fixed<<std::setprecision(15);
int tt=1;cin>>tt;
while(tt--)solve();
return 0;
}
Word
/**
* 令字符串s为s[0],字符串t为s[n+1],其他字符串为s[1-n],每个字符串都对应一个编号
* 双重for循环遍历所有字符串对,若满足转换条件,则对应的编号连接一条权值为1的边,
* 显然满足转换条件当且仅当两个字符串有且仅有一个字符不同.
*
* 显然从s[0]到s[n+1]的最小操作数可以转换为从点0到点n+1的最短路径长度
*
* 因此连完边之后直接跑最短路算法,由于边权都为1,故可直接使用bfs跑最短路,
* 同时用last数组记录路径,
* last[i]表示从s[last[i]]转换到s[i]是从s[0]到s[i]最短路上的最后一步.
* 详见代码.
*/
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using std::cin;
using std::cout;
const int maxn=2e3+5;
const int maxm=4e6+5;
int head[maxn],to[maxm],ne[maxm],id;
void add(int x,int y){
ne[++id]=head[x],head[x]=id,to[id]=y;
ne[++id]=head[y],head[y]=id,to[id]=x;
}
int n,m;
std::string s[maxn];
bool canAddEdge(int i,int j){
int cnt=0;
for(int k=0;k<m;k++){
cnt+=s[i][k]!=s[j][k];
}
return cnt==1;
}
int d[maxn];//从0到i的最短路径
int last[maxn];//从0到i的最短路径上,最后一个是从last[i]到达i
bool vis[maxn];//从0是否可以到达i
void bfs(){
std::queue<int> que;
que.push(0);
vis[0]=true;//每个点在入队之后,其vis值标记为true,表示已经遍历过
d[0]=0;//0->0的距离为0
last[0]=-1;//0->0的路径中,0没有上一个点,标记为-1
while(!que.empty()){
int i=que.front();
que.pop();
for(int e=head[i],id=to[e];e;e=ne[e],id=to[e]){
//id之前已经可以被其他点遍历了,
//根据bfs的特性,此处再次到达的路径和先前的路径长度相等或者更大,不优,因此直接continue即可
if(vis[id])continue;
//id先前还没遍历过,此处是第一次遍历到,必定是最短的距离
que.push(id);
//更新对应的数组值
d[id]=d[i]+1,last[id]=i,vis[id]=true;
}
}
}
void solve(){
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>s[i];
cin>>s[0]>>s[n+1];
for(int i=0;i<=n+1;i++){
for(int j=i+1;j<=n+1;j++){
if(canAddEdge(i,j)){
add(i,j);
}
}
}
//特判掉s==t的情况
if(s[0]==s[n+1]){
cout<<0<<endl;
cout<<s[0]<<endl;
cout<<s[n+1]<<endl;
return;
}
bfs();
if(!vis[n+1]){
cout<<-1<<endl;
return;
}
int now=n+1;
std::vector<int> path;
//从终点n+1,从后往前把最短路径上的点一个一个放进path数组
//如果now==-1,则表示上一轮循环已经把起始点0点放进path数组,故可结束循环
while(now!=-1){
path.push_back(now);
now=last[now];
}
cout<<d[n+1]-1<<endl;
//从起点到终点,逆向打印path中的数组值
for(auto it=path.rbegin();it!=path.rend();it++){
cout<<s[*it]<<endl;
}
}
signed main(){
// freopen("file.txt","r",stdin);
std::ios_base::sync_with_stdio(false);
std::cin.tie(nullptr),std::cout.tie(nullptr);
// cout<<std::fixed<<std::setprecision(15);
int tt=1;//cin>>tt;
while(tt--)solve();
return 0;
}
Operating System
/**
* 贪心:每次需要页面置换时,替换出内存里面下次使用时刻最远的页面
* 使用set模拟内存,记录内存里每一个页面的编号以及下一次使用的时刻
* 运算符重载不仅适用于结构体类型的优先队列,对结构体类型的各种set,map都是适用的!
*/
//#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using std::cin;
using std::cout;
const int maxn=5e4+5;
int n,m,q;
int a[maxn];
int b[maxn];//b是辅助初始化ne数组的,b[a[i]]记录的是a[i]这个数当前时刻出现的位置,详见代码
int ne[maxn];//ne[i]表示a[i]下一次出现的下标位置
struct T{
int id,next;//编号,下次使用时刻
//注意运算符重载next值越大,结果越小!!!,表示按照next降序排列
bool operator <(const T &t)const{
return next>t.next;
}
};
void solve(){
//多组数据初始化
for(int i=1;i<=m;i++)b[i]=0;
for(int i=1;i<=q;i++)cin>>a[i];
//倒叙遍历!!!
for(int i=q;i>=1;i--){
//先更新ne数组,后更新b数组,顺序不能乱
//此时b[a[i]]记录的是上一次记录的a[i]的下标,b[a[i]]不为0则表示在此之前有出现过a[i]这个数
//b[a[i]]为0则代表没有下一次使用,故此时下次使用时刻ne[i]记为最大值(q+1),是最理想的替换页面
ne[i]=(b[a[i]]?b[a[i]]:q+1);
b[a[i]]=i;
}
int ans=0;
std::set<T> set;
for(int i=1;i<=q;i++){
if(set.count({a[i],i})){
//如果set内存里已经有a[i](之前放进内存的),则对应的值一定是{a[i],i}
//因为上一个值为a[i]的下标(假设为j,)放的是{a[j],ne[j]},而a[j]==a[i],ne[j]=i
//改变下一次出现的位置i为ne[i]
set.erase({a[i],i});
set.insert({a[i],ne[i]});
}else{
//set内存里没有a[i],需要添加a[i]号页面,先判断内存是否满
if((int)set.size()==n)set.erase(set.begin());//内存满了,删除下次使用时刻最远的内存页面
set.insert({a[i],ne[i]});//添加页面
ans++;//统计答案
}
}
cout<<ans<<endl;
}
signed main(){
// freopen("file.txt","r",stdin);
std::ios_base::sync_with_stdio(false);
std::cin.tie(nullptr),std::cout.tie(nullptr);
// cout<<std::fixed<<std::setprecision(15);
while(cin>>n>>m>>q){
solve();
}
return 0;
}
阿宁去游玩
/*
此题难就难在,随着膜法的使用,(花费)边的权值可能会有所不同,
但是实际上,在最优情况下,边的权值是固定的!!!
如果当前选中的是i号点,那么在最优情况下,
i点的所有vis值为false的邻点id,其与i点的属性异同性不变,
从起点走到i点的过程中,若经过id点,则vis[id]为true,矛盾,
故从起点走到i点,不会经过id点,
所以从起点走到i点的途中,若使用了膜法,必然i和id两者会同时变化,因此两者异同性不变
"关键在于i点"
如果在i点没使用膜法,则两者异同性不变,花费为cost1=((a[i]^a[j])y:x)
如果在i点使用了膜法,则两者异同性会改变,花费为cost2=z+((a[i]^a[j])?x:y)
最优情况下应该取 min(cost1,cost2),此即为路径长度(边的权值)
因此,对任意的i点都是如此,即对所有的点都满足该条件,所以在最优情况下,边的权值是固定的!
建完图之后直接复制dijkstra模板即可,详见代码
*/
//#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using std::cin;
using std::cout;
const int maxn=2e5+5;
const int maxm=4e5+5;
int head[maxn],to[maxm],ne[maxm],w[maxm],id;
void add(int x,int y,int z){
ne[++id]=head[x],head[x]=id,to[id]=y,w[id]=z;
ne[++id]=head[y],head[y]=id,to[id]=x,w[id]=z;
}
int n,m,x,y,z,d[maxn];
bool a[maxn],vis[maxn];
using pii=std::pair<int,int>;
#define fi first
#define se second
int dijkstra(){
for(int i=1;i<=n;i++)vis[i]=false,d[i]=1e18;
d[1]=0;
std::priority_queue<pii,std::vector<pii>,std::greater<pii>> que;
que.push({d[1],1});
while(!que.empty()){
pii p=que.top();
que.pop();
int i=p.se;
if(vis[i])continue;
vis[i]=true;
for(int e=head[i],id=to[e];e;e=ne[e],id=to[e]){
if(!vis[id]&&d[id]>d[i]+w[e]){
d[id]=d[i]+w[e];
que.push({d[id],id});
}
}
}
return d[n];
}
void solve(){
cin>>n>>m>>x>>y>>z;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=m;i++){
int u,v;
cin>>u>>v;
int cost1=((a[u]^a[v])?y:x);
int cost2=z+((a[u]^a[v])?x:y);
add(u,v,std::min(cost1,cost2));
}
cout<<dijkstra()<<endl;
}
signed main(){
// freopen("file.txt","r",stdin);
std::ios_base::sync_with_stdio(false);
std::cin.tie(nullptr),std::cout.tie(nullptr);
// cout<<std::fixed<<std::setprecision(15);
int tt=1;//cin>>tt;
while(tt--)solve();
return 0;
}