一、wander(梦游)
题目求的是1到n的最短路径,为单元最短路径,故不可用多元最短路径的弗洛伊德算法。最开始想的是弗洛伊德,因为是直接从1到n,故可以简化为两层循环。但是时间应该可以,空间直接爆了。所以正解为spfa算法。
这里贴一个标准SPFA,方便以后复习。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 200005;
struct Vtx {
Vtx *Next;
int To;
long long Wgt;
Vtx(void) : Next(NULL) {}
Vtx(int To, long long Wgt) :
To(To), Wgt(Wgt), Next(NULL) {}
};
struct VtxHead : Vtx {
Vtx *Head;
long long Dist;
void Grow(int To, long long Wgt)
{
if (Head) Next =
Next->Next = new Vtx(To, Wgt);
else Head =
Next = new Vtx(To, Wgt);
}
VtxHead(void) :
Dist(LLONG_MAX), Head(NULL) {}
} G[MAXN], AntiG[MAXN];
struct Unit {
int u;
long long Dist;
bool operator < (const Unit &x) const
{
return Dist > x.Dist;
}
};
inline void Search(VtxHead *Graph, int Source)
{
priority_queue<Unit> Travel;
Travel.push( (Unit) { Source, 0 } );
Graph[Source].Dist = 0;
while (!Travel.empty()) {
int From = Travel.top().u;
long long CrtDist = Travel.top().Dist;
Travel.pop();
for (register Vtx *i = Graph[From].Head;
i; i = i->Next)
if (Graph[From].Dist + i->Wgt <
Graph[i->To].Dist) {
Graph[i->To].Dist =
Graph[From].Dist + i->Wgt;
Travel.push(
(Unit) { i->To, Graph[i->To].Dist } );
}
}
}
int main(void)
{
int n, m;
scanf("%d %d", &n, &m);
while (m--) {
int u, v;
long long Wgt;
scanf("%d %d %lld", &u, &v, &Wgt);
G[u].Grow(v, Wgt);
AntiG[v].Grow(u, Wgt);
}
Search(G, 1);
Search(AntiG, n);
printf("%lld\n", G[n].Dist);
long long MinDist = G[n].Dist;
for (register int i = 1; i <= n; ++i)
for (register Vtx *j = G[i].Head;
j; j = j->Next)
if (G[i].Dist + AntiG[j->To].Dist <
MinDist)
MinDist =
G[i].Dist + AntiG[j->To].Dist;
printf("%lld\n", MinDist);
return 0;
}
二、gene(基因)
一道考察结构体判断函数的写法的题,但是因为题没有读清楚,以为每行随机输入一些数,所以想了很久而且错了。下次要认真读题。
这里要求使用vector,下面复习一下,考试也没有太想清楚。
在c++中,vector是一个十分有用的容器。
作用:它能够像容器一样存放各种类型的对象,简单地说,vector是一个能够存放任意类型的动态数组,能够增加和压缩数据。
vector在C++标准模板库中的部分内容,它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库。
特别注意:
使用vector需要注意以下几点:
1、如果你要表示的向量长度较长(需要为向量内部保存很多数),容易导致内存泄漏,而且效率会很低;
2、Vector作为函数的参数或者返回值时,需要注意它的写法:
double Distance(vector&a, vector&b) 其中的“&”绝对不能少!!!
实例:vectortest;
//建立一个vector,int为数组元素的数据类型,test为动态数组名
简单的使用方法如下:
vectortest;//建立一个vector
test.push_back(1);
test.push_back(2);//把1和2压入vector,这样test[0]就是1,test[1]就是2
1 、基本操作
(1)头文件#include.
(2)创建vector对象,vector vec;
(3)尾部插入数字:vec.push_back(a);
(4)插入元素: vec.insert(vec.begin()+i,a);在第i+1个元素前面插入a;
(5)删除元素: vec.erase(vec.begin()+2);删除第3个元素
vec.erase(vec.begin()+i,vec.end()+j);删除区间[i,j-1];区间从0开始
(6)向量大小:vec.size();
(7)清空:vec.clear();
特别提示:这里有begin()与end()函数、front()与back()的差别
2、重要说明
vector的元素不仅仅可以是int,double,string,还可以是结构体,但是要注意:结构体要定义为全局的,否则会出错。
——————————————————————————————————————————
#include<bits/stdc++.h>
using namespace std;
struct f {
int len;
int num;
vector <int> a;
} fi[1000001];
bool cmp(f x,f y) {
if(x.len==y.len) {
for(int i=0; i<x.len; i++) {
if(x.a[i]!=y.a[i]) return x.a[i]>y.a[i];
if(i==x.len-1) return x.num<y.num;
}
}
return x.len<y.len;
}
int main() {
int n;
cin>>n;
for(int i=1; i<=n; i++) {
int x;
cin>>x;
for(int j=1; j<=x; j++) {
int temp;
cin>>temp;
fi[i].a.push_back(temp);
}
fi[i].len=x;
fi[i].num=i;
}
sort(fi+1,fi+1+n,cmp);
for(int i=1; i<=n; i++) {
if(i!=n)
cout<<fi[i].num<<" ";
else
cout<<fi[i].num;
}
return 0;
}
四、joseph(约瑟夫)
看这个数据规模就知道不能直接模拟,于是找规律。
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
bool Alive[10000000];
int main() {
// freopen("joseph.in","r",stdin);
// freopen("joseph.out","w",stdout);
int m,n;
cin>>n>>m;
if(m != 2) {
int res = 0;
for(int i = 2; i<=n; i++) {
res = (res + m) % i;
}
cout<<res + 1;
} else if(m == 2) {
int temp = m;
while(temp < n) {
temp *= 2;
}
long long ans = temp - 1 - (temp - 1 - n)*2;
cout<<ans;
}
return 0;
}