图论1
9-1 查找文献
题目链接
解题思路
邻接表存图,排序后使用dfs
与bfs
即可。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
const int maxm=1e6+5;
int n,m;
bool vis[maxn];
vector <int> a[maxn];
queue <int> q;
void dfs(int k){
cout<<k<<" ";
int l=a[k].size();
for (int i=0; i<l; i++){
int to=a[k][i];
if (!vis[to]){
vis[to]=1;
dfs(to);
}
}
}
void bfs(int k){
q.push(k);
while (!q.empty()){
int to=q.front();
q.pop();
cout<<to<<" ";
int l=a[to].size();
for (int i=0; i<l; i++){
int next=a[to][i];
if (!vis[next]){
vis[next]=1;
q.push(next);
}
}
}
}
int main(){
cin>>n>>m;
for (int i=1; i<=m; i++){
int u,v;
scanf("%d%d",&u,&v);
a[u].push_back(v);
}
for (int i=1; i<=n; i++){
sort(a[i].begin(),a[i].end());
}
memset(vis,0,sizeof(vis));
vis[1]=1;
dfs(1);
cout<<endl;
memset(vis,0,sizeof(vis));
vis[1]=1;
bfs(1);
return 0;
}
笔者前几天才想明白,dfs
与bfs
使用时必然是联通图的情况,所以只需要dfs(1)
与bfs(1)
就能走遍整个图,不需要再外加一个for(i:1~n)
。
9-2 floyd
题目链接
解题思路
先明白floyd
的原理
本质上是三重循环去找,但是因为递推式右边中都为k-1
,所以空间上可以降为二维。
floyd
是一种动态规划,复杂度比较高,时间复杂度O(N3),是求每对结点之间的最短路,适用于任何图:有向无向、边权正负,但是最短路必须存在。(不能有个负环)
注意: 本题需要取模运算,但只能在最后累加时候取模。在floyd
运算时,即a[i][j]=min(a[i][j],a[i][k]+a[k][j]);
语句中不可取模,否则取模后两个数的大小关系可能会发生改变。
#include<bits/stdc++.h>
using namespace std;
const int maxn=5e2+5;
typedef long long ll;
const ll MOD=998244354;
int n,m;
ll f[maxn][maxn];
ll a[maxn][maxn];
int main(){
cin>>n>>m;
memset(a,0x3f,sizeof(a));
for (int i=1; i<=n; i++){
a[i][i]=0;
}
for (int i=1; i<=m; i++){
ll u,v,w;
cin>>u>>v>>w;
a[u][v]=min(w,a[u][v]);
a[v][u]=min(w,a[v][u]);
}
for (int k=1; k<=n; k++){
for (int i=1; i<=n; i++){
for (int j=1; j<=n; j++){
a[i][j]=min(a[i][j],a[i][k]+a[k][j]);
}
}
}
ll sum=0;
for (int i=1; i<=n; i++){
for (int j=1; j<=n; j++){
sum=(sum+a[i][j])%MOD;
}
cout<<sum<<endl;
sum=0;
}
return 0;
}
9-3 单源最短路径
题目链接
解题思路
Dijkstra
是一种贪心思想,是求单源最短路,适用于非负权图,不能检测负环。
在链式前向星使用和优先队列优化下,时间复杂度O(M logM)。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
const int maxm=2e5+5;
const int inf=0x3f3f3f3f;
int n,m,s;
int f[maxn];
struct node{
int to,w,next;
};
int first[maxn];
node e[maxm];
struct edge{
int w,p;
bool operator <(const edge x) const {
return x.w<w;
}
};
priority_queue <edge> q;
bool vis[maxn];
int main(){
cin>>n>>m>>s;
for (int i=1; i<=m; i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
e[i].to=v;
e[i].w=w;
e[i].next=first[u];
first[u]=i;
}
memset(f,0x3f,sizeof(f));
memset(vis,0,sizeof(vis));
f[s]=0;
q.push({0,s});
while (!q.empty()){
int p=q.top().p;
q.pop();
if (vis[p]){
continue;
}
vis[p]=1;
for (int i=first[p]; i; i=e[i].next){
int to=e[i].to;
int dis=e[i].w;
if (f[to]>f[p]+dis){
f[to]=f[p]+dis;
q.push({f[to],to});
}
}
}
for (int i=1; i<=n; i++){
cout<<f[i]<<" ";
}
return 0;
}