最短路径的dij算法:贪心的找出距离最短的点,由此来松弛其他点
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int maxn = 10005;
const int inf = 0x3f3f3f3f;
typedef long long ll;
int n,m;
int cnt=0;
int head[maxn],d[maxn],v[maxn];
struct node
{
int y,t,p;
}s[maxn<<1];
void add(int n,int m,int k)
{
s[++cnt]=node{m,k,head[n]};
head[n]=cnt;
}
void dij(int x)
{
memset(v,0,sizeof(v));
memset(d,inf,sizeof(d));
d[x]=0;
for(int i=1;i<=n;i++){
int minn=-1;
for(int j=1;j<=n;j++){
if(!v[j]){
if(minn==-1||d[j]<d[minn]){
minn=j;
}
}
}
if(d[minn]==inf)break;
v[minn]=1;
for(int j=head[minn];~j;j=s[j].p){
int a=s[j].y;
int b=s[j].t;
if(!v[a]){
if(d[a]>b+d[minn]){
d[a]=b+d[minn];
}
}
}
}
}
int main()
{
while(~scanf("%d %d",&n,&m)){
if(n==m&&m==0)break;
cnt=0;
memset(head,-1,sizeof(head));
for(int i=1;i<=m;i++){
int a,b,c;
scanf("%d %d %d",&a,&b,&c);
add(a,b,c);
add(b,a,c);
}
dij(1);
printf("%d\n",d[n]);
}
return 0;
}
dij算法用优先队列优化的邻接表方式:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int maxn = 10005;
const int inf = 0x3f3f3f3f;
typedef long long ll;
typedef pair<int,int>p;
int n,m;
int cnt=0;
int head[maxn],d[maxn];
struct node
{
int y,t,p;
friend operator <(node a,node b){
return a.p<b.p;
}
}s[maxn<<1];
void add(int n,int m,int k)
{
s[++cnt]=node{m,k,head[n]};
head[n]=cnt;
}
void dij(int x)
{
memset(d,inf,sizeof(d));
d[x]=0;
p o={0,x};
priority_queue<p>q;
q.push(o);
while(!q.empty()){
p w=q.top();
q.pop();
int r=w.second;
if(d[r]<w.first)continue;
for(int i=head[r];~i;i=s[i].p){
int a=s[i].y;
int b=s[i].t;
if(d[a]>b+d[r]){
d[a]=b+d[r];
q.push(p(d[a],a));
}
}
}
}
int main()
{
while(~scanf("%d %d",&n,&m)){
if(n==m&&m==0)break;
cnt=0;
memset(head,-1,sizeof(head));
for(int i=1;i<=m;i++){
int a,b,c;
scanf("%d %d %d",&a,&b,&c);
add(a,b,c);
add(b,a,c);
}
dij(1);
printf("%d\n",d[n]);
}
return 0;
}
SPFA算法:与BFS思想类似,但是对于一个元素允许出入队列多次:
SPFA还可以运用堆栈的思想来解决,其相当与DFS,而且更快
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int maxn = 10005;
const int inf = 0x3f3f3f3f;
typedef long long ll;
int n,m;
int cnt=0;
int head[maxn],d[maxn],v[maxn];
struct node
{
int y,t,p;
}s[maxn<<1];
void add(int n,int m,int k)
{
s[++cnt]=node{m,k,head[n]};
head[n]=cnt;
}
void spfa(int n)
{
queue<int>q;
memset(v,0,sizeof(v));
memset(d,inf,sizeof(d));
d[n]=0;
q.push(n);
v[n]=0;
while(!q.empty()){
int w=q.front();
q.pop();
v[w]=0;
for(int i=head[w];~i;i=s[i].p){
int a=s[i].y;
int b=s[i].t;
if(d[a]>b+d[w]){
d[a]=b+d[w];
if(!v[a]){
q.push(a);
v[a]=1;
}
}
}
}
}
int main()
{
while(~scanf("%d %d",&n,&m)){
if(n==m&&m==0)break;
cnt=0;
memset(head,-1,sizeof(head));
for(int i=1;i<=m;i++){
int a,b,c;
scanf("%d %d %d",&a,&b,&c);
add(a,b,c);
add(b,a,c);
}
spfa(1);
printf("%d\n",d[n]);
}
return 0;
}
弗洛伊德算法:求出所有点的最短路径,用了动态规划的思想,其中dp[k][i][j]是指在只使用前0~k个点的情况下的从I点到J点的最短路径。
题目:六度分离
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int maxn = 205;
const int inf = 0x3f3f3f3f;
typedef long long ll;
int n,m;
int dp[maxn][maxn];
int main()
{
while(~scanf("%d %d",&n,&m)){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(i==j)
dp[i][j]=0;
else
dp[i][j]=inf;
}
}
int a,b;
for(int i=0;i<m;i++){
scanf("%d %d",&a,&b);
dp[a][b]=dp[b][a]=1;
}
for(int k=0;k<n;k++)
for(int i=0;i<n;i++)
for(int j=0;j<n;j++){
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]);
}
int flag=0;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(dp[i][j]>7){
printf("No\n");
flag=1;
break;
}
}
if(flag==1)
break;
}
if(!flag)
printf("Yes\n");
}
return 0;
}
PS:我太菜了只能做这些模板题。