关于存图
如果是有权值的边,可以用pair
#define pii pair<int,int>
用first存点,用second存权值。
如:
与a相邻的有b点,权值为c。
g[a].push_back({b,c});
若是要遍历与u点相连的点:
//1
vector<pii>g[N];
for(int i=0;i<g[u].size();i++)
{
pii j=g[u][i];
cout<<g[u][i].first<<" "<<g[u][i].second<<endl;//first是点,second是权值
}
//2 auto c++11,在dev里要工具->编译选项-> -std=c++11
//auto可以自动识别类型i,在g[u]里遍历
for(auto i:g[u])
{
cout<<i.first<<" "<<i.second<<endl;
}
bfs
bfs可以理解为一圈一圈、一层一层的搜索,一般与最短距离,最少时间有关。
P4913 【深基16.例3】二叉树深度
代码:
师兄的答案
#include<bits/stdc++.h>
#define N 1000000+5
using namespace std;
vector<int>g[N];
int ans;
int dis[N];//当前层数
void bfs()
{
queue<int>q;
q.push(1);//把1号根节点放进去
while(!q.empty())
{
int t=q.front();
q.pop();
for(auto i:g[t])
{
dis[i]=dis[t]+1;
ans=max(ans,dis[i]);
q.push(i);
}
}
}
int main()
{
int n,a,b;
cin>>n;
//存图
for(int i=1;i<=n;i++)
{
cin>>a>>b;
if(a) g[i].push_back(a);
if(b) g[i].push_back(b);
}
dis[1]=1;
bfs();
cout<<ans;
return 0;
}
dfs
一路走到底,没路了就return。
P3916 图的遍历
反向建图和搜索。
N开小了会RE…
#include<bits/stdc++.h>
#define N 100005
using namespace std;
vector<int>g[N];
int a1[N];
void dfs(int u,int d)
{
if(a1[u]) return;//已经搜过了
a1[u]=d;
for(auto i:g[u])
{
dfs(i,d);
}
}
int main()
{
int n,m,a,b;
cin>>n>>m;
for(int i=0;i<m;i++)
{
cin>>a>>b;
g[b].push_back(a);
}
for(int i=n;i>=1;i--) dfs(i,i);
for(int i=1;i<=n;i++)
{
cout<<a1[i]<<" ";
}
return 0;
}
递归
P1827 [USACO3.4]美国血统 American Heritage
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
char a[N],b[N],n;
void dfs(int la,int ra,int lb,int rb)
{
if(la>ra||lb>rb) return;
int mid=la;
char rt=b[lb];//root
while(a[mid]!=rt) mid++;
dfs(la,mid-1,lb+1,lb+mid-la);//左
dfs(mid+1,ra,lb+mid-la+1,rb);//右
cout<<rt;
}
int main()
{
cin>>a+1>>b+1;//从1开始
n=strlen(a+1);
dfs(1,n,1,n);
return 0;
}
最短路
floyd
P3371 【模板】单源最短路径(弱化版)
虽然过不了,但是还是要知道一下三重循环的floyd。
k当作一个跳板,i到j的距离比较一下i到k,k到j。
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+5;
int g[N][N];
int main()
{
int n,m,s;
cin>>n>>m>>s;
memset(g,0x3f,sizeof g);//a中的每个值都是int的最大值
for(int i=1;i<=n;i++) g[i][i]=0;//我到我自己距离为0
for(int i=1;i<=m;i++)
{
int a,b,c;
cin>>a>>b>>c;
g[a][b]=min(g[a][b],c);//取最小的路
}
//floyd
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
for(int i=1;i<=n;i++)
{
if(g[s][i]!=0x3f3f3f3f) cout<<g[s][i]<<" ";
}
return 0;
}
spfa
#include<bits/stdc++.h>
using namespace std;
const int N=1e4+10;
typedef long long ll;
#define pii pair<int,int>
int n,m,s;
ll dis[N];
bool in[N];//是否在队列里
vector<pii>g[N];
void spfa()
{
for(int i=1;i<=n;i++) dis[i]=1e18;//初始化为无穷大
queue<int>q;
q.push(s);
in[s]=1;//s放进队列了
dis[s]=0;//距离初始化为0;
while(!q.empty())
{
int t=q.front();
q.pop();
in[t]=0;//弹出去之后不在队列里
for(auto i:g[t])
{
int to=i.first,cost=i.second;
if(dis[to]>dis[t]+cost)
{
dis[to]=dis[t]+cost;
if(!in[to])
{
q.push(to);
in[to]=1;
}
}
}
}
}
int main()
{
cin>>n>>m>>s;
for(int i=1;i<=m;i++)
{
int a,b,c;
cin>>a>>b>>c;
g[a].push_back({b,c});
}
spfa();
for(int i=1;i<=n;i++)
{
if(dis[i]==1e18) cout<<(1ll<<31)-1<<" ";//输出2^31-1
else cout<<dis[i]<<" ";
}
return 0;
}
dij
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
#define pii pair<int,int>
#define pll pair<ll,ll>
ll n,m,s,dis[N];
bool st[N];
vector<pii>g[N];
void dij()
{
priority_queue<pll,vector<pll>,greater<pll>>q;
for(int i=1;i<=n;i++) dis[i]=1e18;//先初始化为最大值
q.push({0,s});
dis[s]=0;
while(!q.empty())
{
auto t=q.top();
q.pop();
int now=t.second;
if(st[now]) continue;//已经有最短了
st[now]=1;
for(auto i:g[now])
{
int to=i.first,cost=i.second;
if(dis[to]>dis[now]+cost)
{
dis[to]=dis[now]+cost;
q.push({dis[to],to});
}
}
}
}
int main()
{
cin>>n>>m>>s;
for(int i=0;i<m;i++)
{
int a,b,c;
cin>>a>>b>>c;
g[a].push_back({b,c});
}
dij();
for(int i=1;i<=n;i++) cout<<dis[i]<<" ";
return 0;
}
其他
0x3f int最大值。
被卡可以考虑把queue换成stack。(spfa之类)