区队A 最短路2
floyd
定义
\(f[k][i][j] = min(f[k - 1][i][j],f[k - 1][i][k] + f[k -1][k][j]) = min(f[k - 1][i][j],f[k][i][k] + f[k][k][j])\)
注意到可以省去第一维-->\(min(f[i][j],f[i][k] + f[k][j]\)
代码实现
#include<bits/stdc++.h>
using namespace std;
const int N = 110;
int g[N][N];
signed main()
{
ios::sync_with_stdio(0);cin.tie(0);
int n,m;
cin>>n>>m;
memset(g,0x3f,sizeof(g));
for(int i= 1;i<=n;i++)
{
g[i][i]= 0;
}
for(int i = 1;i<=m;i++)
{
int u,v,w;
cin>>u>>v>>w;
g[u][v] = min(g[u][v] , w);
g[v][u] = min(g[v][u] , w);
}
for(int k = 1;k <= n; k ++)
{
for(int i = 1;i <= n;i++)
{
for(int j =1;j <= n ; j++)
{
g[i][j] = min(g[i][j],g[i][k]+g[k][j]);
}
}
}
for(int i = 1;i<=n;i++)
{
for(int j= 1;j <= n;j ++)
{
cout<<g[i][j] <<' ';
}
cout<<'\n';
}
return 0;
}
P1119 灾后重建
题目分析
首先可以发现题目中的数组\(t\)是保证单调性的,询问中的\(time\)也是单调,于是每一次我们都去扫描时间进行更新-->ans
Code
#include<bits/stdc++.h>
using namespace std;
const int N = 250;
const int M = 1e5+10;
int t[N];
int g[N][N];
signed main(){
ios::sync_with_stdio(0);cin.tie(0);
int n,m;
cin>>n>>m;
for(int i =0;i<n;i++)
{
cin>>t[i];
}memset(g,0x3f,sizeof(g));
for(int i = 0;i<n;i++) g[i][i] = 0;
for(int i = 1;i<=m;i++)
{
int u , v, w;
cin>>u >> v >> w;
g[u][v] = min(g[u][v],w);
g[v][u] = min(g[v][u],w);
}
int Q,ptr = 0;
cin>>Q;
while(Q--)
{
int x,y,time;
cin>>x>>y>>time;
for(; ptr < n && t[ptr] <= time;++ptr)
{
for(int i = 0; i<n;i++)
{
for(int j = 0;j < n ; j++)
{
g[i][j] = min(g[i][j],g[i][ptr]+g[ptr][j]);
}
}
}
if(t[x] > time || t[y] > time || g[x][y] == 0x3f3f3f3f)
{
cout<<"-1\n";
}
else
{
cout<<g[x][y]<<'\n';
}
}
return 0;
}
P6464 [传智杯 #2 决赛] 传送门
题目分析
枚举\(x,y\)去进行修改,然后枚举\(i,j\)==>\(O(n^4)\)
中继点改中继边
Code
#include<bits/stdc++.h>
using namespace std;
const int N = 110;
int g[N][N];
signed main()
{
ios::sync_with_stdio(0);cin.tie(0);
int n,m;
cin>>n>>m;
memset(g,0x3f,sizeof(g));
for(int i= 1;i<=n;i++)
{
g[i][i]= 0;
}
for(int i = 1;i<=m;i++)
{
int u,v,w;
cin>>u>>v>>w;
g[u][v] = min(g[u][v] , w);
g[v][u] = min(g[v][u] , w);
}
for(int k = 1;k <= n; k ++)
{
for(int i = 1;i <= n;i++)
{
for(int j =1;j <= n ; j++)
{
g[i][j] = min(g[i][j],g[i][k]+g[k][j]);
}
}
}int minn = INT_MAX;
for(int x = 1;x < n;x++)
{
for(int y = x + 1;y <= n;y++)
{
int sum = 0;
for(int i = 1;i<=n;i++)
{
for(int j = 1;j<=n;j++)
{
sum += min({g[i][j],g[i][x] + g[y][j],g[i][y] + g[x][j]});
}
}minn = min(minn,sum);
}
}cout<<minn / 2;
return 0;
}
P1522 [USACO2.4] 牛的旅行 Cow Tours
题目分析
我们可以先计算出两点间的最短路径,然后算直径\(d\)
Code
#include<bits/stdc++.h>
using namespace std;
const int N = 160;
int field[N];
double g[N][N],maxd[N],diameter[N];
pair<int,int> pos[N];
double calc_dis(pair<int,int> p1,pair<int,int> p2)
{
return hypot(p1.first - p2.first,p1.second - p2.second);
}
signed main()
{
ios::sync_with_stdio(0);cin.tie(0);
int n,m;
cin>>n;
for(int i = 1;i<=n;i++)
{
for(int j = 1;j <= n;j ++)
{
g[i][j] = INFINITY;
}
}
for(int i = 1;i<=n;i++) cin>>pos[i].first>>pos[i].second;
for(int i= 1;i<=n;i++)
{
g[i][i]= 0;
}
for(int i = 1;i<=n;i++)
{
string s;
cin>>s;
for(int j= 0;j < n;j++)
{
int x = s[j] - '0';
if(x == 1)
{
g[i][j + 1] = calc_dis(pos[i],pos[j + 1]);
}
}
}
for(int k = 1;k <= n; k ++)
{
for(int i = 1;i <= n;i++)
{
for(int j =1;j <= n ; j++)
{
g[i][j] = min(g[i][j],g[i][k]+g[k][j]);
}
}
}
int cnt =0 ;
memset(field,0,sizeof(field));
for(int i = 1;i<=n;i++)
{
if(field[i]== 0)
{
cnt++;
diameter[cnt] = 0;
for(int j = 1;j <=n;j++)
{
if(!isinf(g[i][j]))
{
field[j] = cnt;
}
}
}
}
for(int i= 1;i<=n;i++)
{
double maxx = 0;
for(int j = 1;j <= n;j ++)
{
if(!isinf(g[i][j]))
{
maxx = max(maxx,g[i][j]);
}
}maxd[i] = maxx;
diameter[field[i]] = max(diameter[field[i]],maxx);
}
double ans = INFINITY;
for(int i =1;i<n;i++)
{
for(int j = i + 1; j <= n;j ++)
{
if(field[i] != field[j])
{
ans = min(ans,max({diameter[field[i]],diameter[field[j]],maxd[i] + maxd[j] + calc_dis(pos[i],pos[j])}));
}
}
}
cout<<fixed<<setprecision(6)<<ans;
return 0;
}
P3371 【模板】单源最短路径(弱化版)
Code
#include <bits/stdc++.h>
using namespace std;
bool in_queue[10001];
int dis[10001];
vector<pair<int, int>> edge[10001];
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m, s;
cin >> n >> m >> s;
for (int i = 1; i <= m; ++i) {
int u, v, w;
cin >> u >> v >> w;
edge[u].push_back({v, w});
}
memset(in_queue, false, sizeof(in_queue));
memset(dis, 0x3F, sizeof(dis));
queue<int> que;
in_queue[s] = true;
dis[s] = 0;
que.push(s);
while (!que.empty()) {
int u = que.front();
que.pop();
in_queue[u] = false;
for (int i = 0; i < edge[u].size(); ++i) {
int v = edge[u][i].first, w = edge[u][i].second;
if (dis[v] > dis[u] + w) {
dis[v] = dis[u] + w;
if (!in_queue[v]) {
que.push(v);
in_queue[v] = true;
}
}
}
}
for (int i = 1; i <= n; ++i) {
cout << (dis[i] != 0x3F3F3F3F ? dis[i] : INT_MAX) << ' ';
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
struct edge
{
int v,w;
};
vector<edge> e[N];
int dis[N],n,m;
int T , cnt[N];
bool vis[N];
bool spfa(int s)
{
queue<int> q;
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
memset(cnt,0,sizeof(cnt));
dis[s] = 0;
q.push(s);
vis[s] = 1;
cnt[s] = 0;
while(q.size())
{
int u = q.front();
q.pop();
vis[u] = 0;
for(auto ed : e[u])
{
int v = ed.v,w = ed.w;
if(dis[v] > dis[u] + w)
{
dis[v] = dis[u] + w;
if(!vis[v])
{
q.push(v);
vis[v]= 1;
cnt[v] ++;
if(cnt[v] >= n) return 0;
}
}
}
}return 1;
}
void solve()
{
memset(e,0,sizeof(e));
int s;
cin>>n>>m>>s;
for(int i= 1,a,b,c;i <= m ; i++)
{
cin>>a>>b>>c;
e[a].push_back({b,c});
}spfa(s);
for(int i =1;i<=n;i++)
{
if(dis[i] >= 0x3f3f3f3f)
{
cout<<INT_MAX<<' ';
}
else{
cout<<dis[i]<<' ';
}
}
}
signed main()
{
ios::sync_with_stdio(0);cin.tie(0);
T = 1;
while(T--)
{
solve();
}
return 0;
}
P3385 【模板】负环
Code
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
const unsigned Mod = 2001;
struct edge
{
int v,w;
};
vector<edge> e[N];
int dis[N],n,m;
int T , cnt[N];
bool vis[N];
bool spfa(int s)
{
bool in_queue[2010];
int que[2010];
memset(in_queue,0,sizeof(in_queue));
memset(dis,0x3f,sizeof(dis));
memset(cnt,0,sizeof(cnt));
unsigned front = 1,tail = 0;
in_queue[1] = 1;
dis[1]= 0;
cnt[1] = 1;
que[++tail] = 1;
bool flag = 0;
while(front <= tail)
{
int u = que[(front++) % Mod];
in_queue[u] = 0;
for(int i = 0; i < e[u].size() ; i ++)
{
int v = e[u][i].v,w = e[u][i].w;
if(dis[v] > dis[u] + w)
{
dis[v] = dis[u]+w;
cnt[v] = cnt[u] + 1;
if(cnt[v] > n)
{
return 0;
}
if(!in_queue[v])
{
que[(++tail) % Mod] = v;
in_queue[v] = 1;
}
}
}
}return 1;
}
void solve()
{
for(int i= 1;i<=n;i++)
{
e[i].clear();
}
cin>>n>>m;
for(int i= 1,a,b,c;i <= m ; i++)
{
cin>>a>>b>>c;
if(c >= 0)
{
e[a].push_back({b,c});
e[b].push_back({a,c});
}
else
{
e[a].push_back({b,c});
}
}if(!spfa(1))
{
cout<<"YES\n";
}
else
{
cout<<"NO\n";
}
}
signed main()
{
ios::sync_with_stdio(0);cin.tie(0);
cin>>T;
while(T--)
{
solve();
}
return 0;
}
tips
循环队列在这种情况之下的速度回避\(STL中的queue\)快
P5960 【模板】差分约束
Code
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
const unsigned Mod = 5e3+10;
struct edge
{
int v,w;
};
vector<edge> e[N];
int dis[N],n,m;
int T , cnt[N];
bool vis[N];
bool spfa(int s)
{
bool in_queue[Mod];
int que[Mod];
memset(in_queue,0,sizeof(in_queue));
memset(dis,0x3f,sizeof(dis));
memset(cnt,0,sizeof(cnt));
unsigned front = 1,tail = 0;
in_queue[s] = 1;
dis[s]= 0;
cnt[s] = 1;
que[++tail] = s;
bool flag = 0;
while(front <= tail)
{
int u = que[(front++) % Mod];
in_queue[u] = 0;
for(int i = 0; i < e[u].size() ; i ++)
{
int v = e[u][i].v,w = e[u][i].w;
if(dis[v] > dis[u] + w)
{
dis[v] = dis[u]+w;
cnt[v] = cnt[u] + 1;
if(cnt[v] > n + 1)
{
return 0;
}
if(!in_queue[v])
{
que[(++tail) % Mod] = v;
in_queue[v] = 1;
}
}
}
}return 1;
}
void solve()
{
cin>>n>>m;
for(int i= 1,a,b,c;i <= m ; i++)
{
cin>>a>>b>>c;
e[b].push_back({a,c});
}for(int i = 1;i<=n;i++)
{
e[0].push_back({i,0});
}
if(spfa(0))
{
for(int i=1 ;i<=n;i++)
{
cout<<dis[i]<<' ';
}
}
else
{
cout<<"NO\n";
}
}
signed main()
{
ios::sync_with_stdio(0);cin.tie(0);
T = 1;
while(T--)
{
solve();
}
return 0;
}
P4578 [FJOI2018] 所罗门王的宝藏
Code
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
const unsigned Mod = 5e3+10;
struct edge
{
int v,w;
};
vector<edge> e[N];
int dis[N],n,m;
int T , cnt[N];
bool vis[N];
bool spfa(int s)
{
bool in_queue[Mod];
int que[Mod];
memset(in_queue,0,sizeof(in_queue));
memset(dis,0x3f,sizeof(dis));
memset(cnt,0,sizeof(cnt));
unsigned front = 1,tail = 0;
in_queue[s] = 1;
dis[s]= 0;
cnt[s] = 1;
que[++tail] = s;
bool flag = 0;
while(front <= tail)
{
int u = que[(front++) % Mod];
in_queue[u] = 0;
for(int i = 0; i < e[u].size() ; i ++)
{
int v = e[u][i].v,w = e[u][i].w;
if(dis[v] > dis[u] + w)
{
dis[v] = dis[u]+w;
cnt[v] = cnt[u] + 1;
if(cnt[v] > n + m+ 1)
{
return 0;
}
if(!in_queue[v])
{
que[(++tail) % Mod] = v;
in_queue[v] = 1;
}
}
}
}return 1;
}
void solve()
{
int k;
cin>>n>>m>>k;
for(int i= 1;i<=n + m ; i ++)
{
e[i].clear();
}
for(int i= 1,a,b,c;i <= k ; i++)
{
cin>>a>>b>>c;
e[a].push_back({b + n,-c});
e[b + n].push_back({a,c});
}for(int i = 1;i<=n;i++)
{
e[0].push_back({i,0});
}
if(spfa(0))
{
cout<<"Yes\n";
}
else
{
cout<<"No\n";
}
}
signed main()
{
ios::sync_with_stdio(0);cin.tie(0);
cin>>T;
while(T--)
{
solve();
}
return 0;
}

浙公网安备 33010602011771号