区队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;
}
posted @ 2026-09-08 13:21  Zhenggeek  阅读(4)  评论(0)    收藏  举报