题目地址:http://sdau.openjudge.cn/graph/

 

dijkstra求最短路径

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N=200005;
int n,m,st,en;
bool vis[N];//标记数组
ll dist[N];//距离数组
int pre[N];//前驱
int head[N],tot;
//结构体数组edge存边,edge[i]表示第i条边,
//head[i]存以i为起点的第一条边(在edge中的下标)
struct node
{
int next; //下一条边的存储下标
int to; //这条边的终点
ll w;//权值
} edge[N*4];
///tot为边的计数,从0开始计,每次新加的边作为第一条边,最后倒序遍历
void add(int u,int v,ll w)
{
edge[tot].to=v;
edge[tot].w=w;
edge[tot].next=head[u];
head[u]=tot++;
}
void init()
{
tot=0;
memset(head,-1,sizeof(head));
memset(pre,-1,sizeof(pre));
}

struct Rec
{
int id; //节点编号
ll dis; //距离
/*bool operator<(const Rec &tmp)const{
return dis>tmp.dis;
} */
};
bool operator <(const Rec&a,const Rec&b)
{
return a.dis>b.dis;
}
priority_queue<Rec> q;//重载小于号实现小根堆

void dijkstra()
{
for(int i=0; i<=n; i++)
dist[i]=1e18;
memset(vis,0,sizeof(vis));

dist[st]=0;
Rec rec;rec.id=st;rec.dis=0;
q.push(rec);
while(!q.empty())
{
int u=q.top().id;

q.pop();
if(vis[u])
continue;
vis[u]=1;
for(int i=head[u]; i!=-1; i=edge[i].next) //遍历以u为起点的所有边,与输入顺序相反
{
int v=edge[i].to;
ll w=edge[i].w;
if(dist[v]>dist[u]+w)
{
dist[v]=dist[u]+w;
Rec rec;
rec.id=v;
rec.dis=dist[v];
q.push(rec);
pre[v]=u;
}
}
}
}
vector<int> path;
void getPath()
{
for(int i=en; i!=-1; i=pre[i])
{
path.push_back(i);
}
}
int main()
{

scanf("%d%d",&n,&m);
st=1;en=n;
scanf("%d%d",&st,&en);
int u,v;
ll w;
init();
for(int i=1; i<=m; i++)
{
scanf("%d%d%lld",&u,&v,&w);
add(u,v,w);
}
dijkstra();
if(dist[en]==1e18)
{
cout<<"no answer"<<endl;
}
else
{
cout<<dist[en]<<endl;
getPath();
for(int i=path.size()-1;i>=0;i--)
{
cout<<"v"<<path[i]<<" ";
}
cout<<endl;
}

return 0;

}

floyd求最短路径

 

#include <bits/stdc++.h>
using namespace std;
const int N=1000;
int n,m;
int dist[N][N];
vector<int> path[N][N];
int main()
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
dist[i][j]=1e9;
for(int i=1;i<=m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
dist[u][v]=w;
path[u][v].push_back(u);
path[u][v].push_back(v);
}
for(int k=0;k<n;k++)
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
if(dist[i][j]>dist[i][k]+dist[k][j])
{
dist[i][j]=dist[i][k]+dist[k][j];
path[i][j].clear();
for(int t=0;t<path[i][k].size()-1;t++)
path[i][j].push_back(path[i][k][t]);

for(int t=0;t<path[k][j].size();t++)
path[i][j].push_back(path[k][j][t]);

}
}
int flag=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(i==j) continue;
cout<<dist[i][j]<<" ";
for(int t=0;t<path[i][j].size();t++)
cout<<"v"<<path[i][j][t]<<" ";
cout<<endl;
flag=1;
}
}
if(flag==0) cout<<"no answer"<<endl;
return 0;
}

求关键路径

#include <bits/stdc++.h>
using namespace std;
const int N=1000;
int head[N],tot;
int ve[N],vl[N],ee[N],el[N];
//ve[i]:顶点i最早开始的时间,vl[i]:顶点i最晚开始的时间
//et[i]:边i最早开始的时间, el[i]:边i最晚开始的时间
stack<int> s;//保存反向拓扑的序列
queue<int> ans_q;
struct node
{
int to;
int next;
int w;
}edge[N*2];
void add(int u,int v,int w)
{
edge[tot].to=v;
edge[tot].w=w;
edge[tot].next=head[u];
head[u]=tot++;
}
int n,m;
int in[N],out[N];
int topo() //求出点的最早发生时间
{
priority_queue<int,vector<int>,greater<int> > q;
for(int i=1;i<=n;i++)
{
if(in[i]==0)
q.push(i);
}
while(!q.empty())
{
int u=q.top();
s.push(u);

q.pop();
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
in[v]--;
if(in[v]==0)
q.push(v);

if(ve[v]<ve[u]+edge[i].w)
{
ve[v]=ve[u]+edge[i].w;
}
}
}
/*for(int i=1;i<=n;i++)
{
cout<<ve[i]<<" ";
}
cout<<endl; */

}
int ReverseTopo()
{
memset(vl,127,sizeof(vl));

for(int i=1;i<=n;i++)
{
if(out[i]==0)
{
vl[i]=ve[i];
}
}

while(!s.empty())
{
int u=s.top();
s.pop();
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(vl[u]>vl[v]-edge[i].w)
{
vl[u]=vl[v]-edge[i].w;
}
}
}
/*for(int i=1;i<=n;i++)
{
cout<<vl[i]<<" ";
}
cout<<endl; */
}
vector<int>ans;
int main()
{
tot=0;
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
in[v]++;
out[u]++;
}
topo();
ReverseTopo();
int endd;
for(int u=1;u<=n;u++)
{
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
int w=edge[i].w;
ee[u]=ve[u];//边最早发生的时间
el[u]=vl[v]-w;边最晚发生的时间
if(ee[u]==el[u])
{
ans.push_back(u);
endd=v;
}
}
}
for(int i=0;i<ans.size();i++)
{
cout<<"v"<<ans[i]<<" ";
}
cout<<"v"<<endd;
return 0;
}

拓扑排序

#include <bits/stdc++.h>
using namespace std;
const int N=1000;
int head[N],tot;
struct node
{
int to;
int next;
int w;
}edge[N*2];
void add(int u,int v)
{
edge[tot].to=v;
edge[tot].next=head[u];
head[u]=tot++;
}
int n,m;
int in[N];
int topo()
{
priority_queue<int,vector<int>,greater<int> > q;
for(int i=1;i<=n;i++)
{
if(in[i]==0)
q.push(i);
}
while(!q.empty())
{
int u=q.top();
q.pop();
cout<<"v"<<u<<" ";
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
in[v]--;
if(in[v]==0)
q.push(v);
}
}

}
int main()
{
tot=0;
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
in[v]++;
}
topo();
return 0;
}

kruskal算法求最小生成树

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1000;
int head[N],tot,fa[N];
int n,m;
struct node
{
int from;
int to;
int next;
ll w;
} edge[N*N];
bool operator<(node a,node b)
{
return a.w<b.w;
}
void add(int u,int v,ll w)
{
edge[tot].from=u;
edge[tot].to=v;
edge[tot].w=w;
edge[tot].next=head[u];
head[u]=tot++;
}
int get(int x)
{
if(x==fa[x])
return x;
else
return fa[x]=get(fa[x]);
}

bool cmp(node x,node y)
{
if(x.from==y.from)
return x.to<y.to;
else
return x.from<y.from;
}
ll a[N][N];
vector<node> ans;
int main()
{
tot=0;
memset(head,-1,sizeof(head));
for(int i=0; i<N; i++)
{
fa[i]=i;
}
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
{
scanf("%lld",&a[i][j]);
}
for(int i=1; i<=n; i++)
for(int j=i+1; j<=n; j++)
{
if(a[i][j]==100)
continue;
if(i==j)
continue;
add(i,j,a[i][j]);
}


sort(edge,edge+m);

int cnt=0;
for(int i=0; i<m; i++)
{

int fu=get(edge[i].from);
int fv=get(edge[i].to);
if(fu!=fv)
{
node temp;
temp.from=edge[i].from;
temp.to=edge[i].to;
ans.push_back(temp);
fa[fu]=fv;
cnt++;
if(cnt==n-1)
break;

}
}
//sort(ans.begin(),ans.end(),cmp);
for(int i=0;i<cnt;i++)
{
cout<<ans[i].from<<" "<<ans[i].to<<" ";
}
return 0;
}

prim算法求最小生成树

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1000;
int n,m;
int a[N][N];

vector<int> ans;
int d[N],vis[N];
void prim()
{
memset(d,127,sizeof(d));
memset(vis,0,sizeof(vis));
d[1]=0;
int pre=1;
for(int i=1;i<=n;i++)
{
int x=0;
for(int j=1;j<=n;j++)
{
if(vis[j]==0&&(x==0||d[j]<d[x]))
{
x=j;

}
}
vis[x]=1;
int temp=x;
for(int y=1;y<=n;y++)
{
if(vis[y]==0)
{
if(d[y]>a[x][y])
{
d[y]=a[x][y];
}
}
}
ans.push_back(d[x]);
pre=x;
}
}
int main()
{
scanf("%d%d",&n,&m);
memset(a,127,sizeof(a));
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
{
if(a[i][i]==100)continue;
scanf("%d",&a[i][j]);
}
prim();

for(int i=1;i<n;i++)
{
cout<<ans[i]<<" ";
}
return 0;
}