dijkstra 堆优化
这是一个稀疏图,所以选择堆优化,稀疏的意思是,点多边也多,所以稀疏
使用堆进行选择
PII vector greater
#include <iostream>
#include <vector>
#include <cstring>
#include <queue>
using namespace std;
const int N = 1e5+10;
vector<pair<int,int>> v[N];
typedef pair<int,int> PII;
int dist[N];
int n,m;
int INF = 0x3f3f3f3f;
bool st[N];
int dijkstra(){
priority_queue<PII,vector<PII>,greater<PII>> heap;//first 距离 second 点
heap.push({0,1});
while(heap.size()){
auto t = heap.top();
heap.pop();
int ver = t.second,distance = t.first;
if(st[ver]) continue;
st[t.second] = 1;
for(auto i:v[ver]){
int tmp = i.first;
if(dist[tmp] > distance + i.second){
dist[tmp] = distance + i.second;
heap.push({dist[tmp],tmp});
}
}
}
if(dist[n]!=INF)
return dist[n];
else
return -1;
}
int main() {
cin>>n>>m;
for(int i = 0; i<m;i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
v[a].push_back({b,c});
}
memset(dist,INF,sizeof dist);
dist[1] = 0;
int res = dijkstra();
cout<<res;
return 0;
}
#include <iostream>
#include <cstring>
using namespace std;
const int N = 1e4+10,INF = 0x3f3f3f3f;
struct edge{
int a,b,c;
}e[N];
int dist[505],back_up[505];
int n,m,k;
void bf(){
for(int i = 0;i<k;i++){
memcpy(back_up,dist,sizeof dist);
for(int j = 0;j < m;j++) {
int a = e[j].a,b = e[j].b,c = e[j].c;
dist[b] = min(dist[b],back_up[a]+c);
}
}
}
int main() {
cin>>n>>m>>k;
memset(dist,INF,sizeof dist);
for(int i = 0;i<m;i++){
scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].c);
}
dist[1] = 0;
bf();
if(dist[n]>=INF/2){
cout<<"impossible";
}
else
cout<<dist[n];
return 0;
}
也可以用来测正权图,类似dijkstra 具体思想就是每次去修改自己的邻接边,如果可以改就改 改一直到队列为空即可
#include <iostream>
#include <vector>
#include <cstring>
#include <queue>
using namespace std;
const int N = 1e5+10,INF = 0x3f3f3f3f;
int n,m;
typedef pair<int,int> PII;
vector<PII> tu[N];
int dist[N];
bool st[N];
queue<int> q;
int spfa(){
dist[1] = 0;
q.push(1);
st[1] = 1;
while(!q.empty()){
int t = q.front();
st[t] = 0;
q.pop();
for(auto i:tu[t]){
int b = i.first,w = i.second;
if(dist[b]>dist[t]+w)
{
dist[b] = dist[t] +w;
if(!st[b]){
q.push(b);
st[b] = 1;
}
}
}
}
if(dist[n]==INF){
return -INF;
}else {
return dist[n];
}
}
int main() {
cin>>n>>m;
for(int i = 0;i<m;i++){
int a,b,w;
scanf("%d%d%d",&a,&b,&w);
tu[a].push_back({b,w});
}
memset(dist,INF, sizeof dist);
int res = spfa();
if(res == -INF)
cout<<"impossible";
else
cout<<res;
return 0;
}
spfa判断负环
需要注意 要把所有的点都放到队列里面,然后再去找cnt大于等于n的点
#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
const int N = 1e5+10,INF = 0x3f3f3f3f;
typedef pair<int,int> PII;
vector<PII> v[N];
queue<int> q;
int dist[N];
int cnt[N];//用于判断负环新增的
int n,m;
int st[N];
int spfa(){
for(int i = 1;i<=n;i++){
q.push(i);
st[i] = 1;
}
while(!q.empty()){
int t = q.front();
q.pop();
st[t] = 0;
for(auto i:v[t]){
int b = i.first;
int w = i.second;
if(dist[b]>dist[t]+w){
dist[b] = dist[t] +w;
cnt[b] = cnt[t]+1;
if(cnt[b] >= n) return -1;
if(!st[b]){
q.push(b);
st[b] = 1;
}
}
}
}
return 0;
}
int main() {
cin>>n>>m;
for(int i = 0;i<m;i++){
int a,b,w;
scanf("%d%d%d",&a,&b,&w);
v[a].push_back({b,w});
}
memset(dist,INF,sizeof dist);
int res = spfa();
if(res == -1){
cout<<"Yes";
}
else
puts("No");
return 0;
}
floyd
三重循环求值 动态规划
#include <iostream>
using namespace std;
const int N = 205,INF = 1e9;
int n,m,q;
int d[N][N];
void folyed(){
for(int k = 1;k<=n;k++){
for(int i = 1;i<=n;i++){
for(int j = 1;j<=n;j++){
d[i][j] = min(d[i][j],d[i][k]+d[k][j]);
}
}
}
}
int main() {
scanf("%d%d%d",&n,&m,&q);
for(int i = 1;i<=n;i++){
for(int j = 1;j<=n;j++){
if(i==j) d[i][j] = 0;
else d[i][j] = INF;
}
}
while(m--){
int a,b,w;
scanf("%d%d%d",&a,&b,&w);
d[a][b] = min(d[a][b],w);
}
folyed();
while(q--){
int a,b;
scanf("%d%d",&a,&b);
if(d[a][b]>=INF/2)
printf("impossible\n");
else
printf("%d\n",d[a][b]);
}
return 0;
}