昨天学习了图的深搜广搜,拓扑排序,先自己写了一遍昨天学习的代码
树的重心
#include<cstring>
#include<iostream>
using namespace std;
const int N=100010;
int h[N],idx,e[N*2],ne[N*2],n,st[N];
int ans=N;
void add(int a,int b){
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
int dfs(int x){
int nu=0,bu=0;
for(int i=h[x];i!=-1;i=ne[i]){
if(!st[e[i]]){
st[e[i]]=1;
int su=dfs(e[i]);
nu+=su;
bu=max(bu,su);
}
}
bu=max(bu,n-nu-1);
ans=min(ans,bu);
return nu+1;
}
int main(){
cin>>n;
memset(h,-1,sizeof h);
for(int i=0;i<n-1;i++){
int a,b;
cin>>a>>b;
add(a,b),add(b,a);
}
dfs(1);
cout<<ans;
return 0;
}
图中点的层次
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
const int N=100010;
int h[N],e[N],ne[N],idx,n,m,d[N];
void add(int a,int b){
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void bfs(int x){
queue<int>q;
memset(d,-1,sizeof d);
d[x]=0;
q.push(x);
while(q.size()){
int t=q.front();
// cout<<t<<' ';
q.pop();
for(int i=h[t];i!=-1;i=ne[i]){
int tt=e[i];
if(d[tt]==-1){
q.push(tt);
// cout<<t<<' '<<d[t]<<' ';
// cout<<tt<<' ';
d[tt]=d[t]+1;
if(tt==n)return ;
}
}
}
}
int main(){
memset(h,-1,sizeof h);
cin>>n>>m;
for(int i=1;i<=m;i++){
int a,b;
cin>>a>>b;
add(a,b);
}
bfs(1);
cout<<d[n];
}
有向图的拓扑序列
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
const int N=100010;
int ru[N],cu[N],h[N],idx,e[N],ne[N],st[N];
int n,m;
void add(int x,int y){
e[idx]=y;
ne[idx]=h[x],h[x]=idx++;
ru[y]++,cu[x]++;
}
vector<int>cc;
void tp(){
queue<int>q;
int ip=1;
for(int i=1;i<=n;i++){
if(!ru[i]){
q.push(i);
cc.push_back(i);
}
}
while(q.size()){
int t=q.front();
q.pop();
for(int i=h[t];i!=-1;i=ne[i]){
int tt=e[i];
ru[tt]--;
if(!ru[tt]){
q.push(tt);
cc.push_back(tt);
}
}
}
// cout<<q.size();
if(cc.size()==n){
for(auto it:cc){
cout<<it<<' ';
}
}else cout<<-1;
}
int main(){
cin>>n>>m;
memset(h,-1,sizeof h);
for(int i=1;i<=m;i++){
int x,y;
cin>>x>>y;
add(x,y);
}
tp();
}
随后直播课搜索与图论(3)看了一半
知识点总结:
最短路问题 n表示图点的个数,m表示边数 1.单元最短路 (1)边权都为正数 方案:a.朴素dijkstra算法 时间复杂度O(n^2) 适用于稠密图(邻接矩阵来存):m与n^2一个级别 b.堆优化的Dijkstra算法 时间复杂度O(mlogn) 稀疏图(邻接表来存):(m与n一个级别) (2)存在负权边 方案:a.BellmanFord算法 时间复杂度O(n*m) b.SPFA 一般平均时间复杂度O(m)最坏O(n*m) 但是对于经过不超过k条边问题只能用BellmanForyd 2.多源汇最短路 Floyd 时间复杂度O(n^3)
随后自己写了两个模板题
Dijkstra求最短路 I
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int N=100010;
int lin[510][510];
int dist[510],st[510];
int n,m;
int dijk(int x){
memset(dist,0x3f,sizeof dist);
dist[1]=0;
for(int i=1;i<n;i++){
int t=-1;
for(int j=1;j<=n;j++){
if(!st[j]&&(t==-1||dist[j]<dist[t])){
t=j;
}
}
st[t]=1;
for(int k=1;k<=n;k++){
if(dist[k]>dist[t]+lin[t][k]){
dist[k]=dist[t]+lin[t][k];
}
}
}
if(dist[x]==0x3f3f3f3f)return -1;
else return dist[x];
}
int main(){
memset(lin,0x3f,sizeof lin);
cin>>n>>m;
for(int i=1;i<=m;i++){
int x,y,z;
cin>>x>>y>>z;
if(z<lin[x][y])lin[x][y]=z;
}
cout<<dijk(n);
return 0;
}
Dijkstra求最短路 II
//出现的问题:第一次用priority_queue 定义不熟悉 后面两个参数应该与第一个参数保持一致
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int N=150010;
int dist[N];
int h[N],e[N],ne[N],idx,w[N];
int st[N];
int n,m;
void add(int x,int y,int z){
ne[idx]=h[x],e[idx]=y,w[idx]=z,h[x]=idx++;
}
int dijks(int x){
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >p;
memset(dist,0x3f,sizeof dist);
dist[1]=0;
p.push({0,1});
while(p.size()){
auto t=p.top();
p.pop();
int der=t.second,di=t.first;
if(st[der])continue;//不写会TLE
st[der]=1;
for(int i=h[der];i!=-1;i=ne[i]){
int xx=e[i],yy=w[i];
dist[xx]=min(dist[xx],dist[der]+w[i]);
p.push({dist[xx],xx});
}
}
if(dist[x]==0x3f3f3f3f)return -1;
else return dist[x];
}
int main(){
memset(h,-1,sizeof h);
cin>>n>>m;
for(int i=1;i<=m;i++){
int x,y,z;
cin>>x>>y>>z;
add(x,y,z);
}
cout<<dijks(n);
return 0;
}
明日任务:把直播课搜索与图论(2)看完 然后自己写一遍明天要学的模板 放松的时候多抄抄今天的模板dijkstra与明天将要学的模板 奢望:以上能够比较快的完成,然后学习3的内容