目前已完成
ABC
小总结: 如果一个问题是单调的,就可以用dij的思想
首先,更广泛的去明白“单调”——即不变的,单一的性质
譬如,单调增的性质(体现在数上面,随着i向前推进): a i < a i+1
A:
dij模板题
using namespace std;
const int N=2100,inf=0x3f3f3f3f;
struct Edge{
int u,v,w;
};
vector <Edge> eg[N];
int d[N];
bool st[N];
void dij(){
memset(d,inf,sizeof d);//ms(v,0);
priority_queue<PII,vector<PII>,greater<PII> >pq;
pq.push({0,1});
d[1]=0;
while(!pq.empty()){
PII now = pq.top();
pq.pop();
int u = now.second;
if(st[u])
continue;
st[u] = 1;
for (int i = 0; i < eg[u].size();i++)
{
int v = eg[u][i].v, w = eg[u][i].w;
if(d[v]>d[u]+w){
d[v] = d[u] + w;
//pre[v]=u;
pq.push({d[v], v});
}
}
}
}
int main(){
int t,n;cin>>t>>n;
For(i,1,t){
int u,v,w;cin>>u>>v>>w;
eg[u].push_back({u,v,w});
eg[v].push_back({v,u,w});
}
dij();
cout<<d[n]<<endl;
return 0;
}
B:
求1-2的可行路径中,找到每条路最长的那条边,再取得所有路得最长边中的最短那个边就是
floyd:
三个for循环不变,k重…允许从1…到k个结点…递推
f函数变化,f[ i ][ j ] 表示 从i-j这条路上的最大值的最小值
f [ j ] [i] = f[i][j] = min(f[i][j], max(f[i][k] , f[k][j]));
dij: 维护d[ N ],为 1-x 路线的 答案(最小的最长边)
(假定被更新对象为d[ k ] ,那么只有用 d[ i ] (d[ i ] < d[ k ] ) 才可能更新 )
const int N=210,inf=0x3f3f3f3f;
struct po{
int x, y;
} p[N];
double dis(po a, po b) {return sqrt(pow(a.x - b.x, 2) + pow(a.y - b.y, 2));}
double f[N][N];
int main(){
int k = 0;
while(1){
k++;
int n;
cin >> n;
if(n==0)break;
ms(p, 0);
ms(f, 0);
_for(i,0,n){
cin >> p[i].x >> p[i].y;
}
_for(i, 0, n) _for(j, 0, n) f[j][i]=f[i][j] = dis(p[i], p[j]);
_for(k,0,n)_for(i, 0, n) _for(j, 0, n){
f[j][i] = f[i][j] = min(f[i][j], max(f[i][k] , f[k][j]));
}
printf("Scenario #%d\nFrog Distance = %.3f\n\n",k,f[0][1]);
}
cout << endl;
return 0;
}
dij:类似与A题,判断条件改一下
for (int i = 0; i < eg[u].size();i++)
{
int v = eg[u][i].v;double w = eg[u][i].w;
double Min=max(d[u],w);
if(d[v]>Min){
d[v] = Min;
//pre[v]=u;
pq.push({d[v], v});
}
}
C题 与B题类似
求的是
最小的那条边(因为一条路中的允许重量取决于最小值),再把每条路中最小的这条边中取最大的
用dij: 思路 : 为了确定 1-n最短路 先确定 1 - i1 的最短路 , 在确定 1-i2…
一直确定到 1-n…
主要是维护d 数组
最短路里代表从起始点到达当前点的最短路径
(prim算法里的则代表把 当前点连入 到 已经连好的部分图形 中的最小距离)
这个题中数组则 代表从 起始点 到达当前点的 最大承重
#include <iostream>
#include <cstring>
#include <string>
#include<cstdio>
#include<map>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#define ll long long
#define PII pair<int, int>
#define PDI pair<double,int>
#define _for(i, a, b) for (int i = a; i < b; i++)
#define For(i, a, b) for (int i = a; i <= b; i++)
#define foR(i, b, a) for (int i = b; i >= a; i--)
#define ms(a,b) memset(a, b, sizeof a)
#define gcd(a, b) __gcd(a, b)
#define lcm(a, b) a / gcd(a, b) * b
#define plf(a) printf("%lf\n",a)
#define sc3(a,b,c) scanf("%d%d%d",&a,&b,&c)
using namespace std;
const int N=2100,inf=0x3f3f3f3f;
struct Edge{
int u,v,w;
};
vector <Edge> eg[N];
int d[N];
bool st[N];
void dij(){
ms(d,0);
ms(st,0);
priority_queue<PII>pq;
pq.push({inf,1});
d[1]=inf;
while(!pq.empty()){
PII now = pq.top();
pq.pop();
int u = now.second;
if(st[u])
continue;
st[u] = 1;
for (int i = 0; i < eg[u].size();i++)
{
int v = eg[u][i].v, w = eg[u][i].w;
int Max=min(d[u],w);
if(d[v]<Max){
d[v] = Max;
//pre[v]=u;
pq.push({d[v], v});
}
}
}
}
int main(){
int t;cin>>t;
For(k,1,t){
int n,m;
cin>>n>>m;
ms(eg,0);
For(i,1,m){
int u,v,w;sc3(u,v,w);
eg[u].push_back({u,v,w});
eg[v].push_back({v,u,w});
}
dij();
printf("Scenario #%d:\n%d\n\n",k,d[n]);
}
return 0;
}
用最小生成树去写: