【集训】最短路!
最短路
P4779 【模板】单源最短路径(标准版)
#include <bits/stdc++.h>
using namespace std;
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
#define ROF(i, a, b) for (int i = (a); i >= (b); --i)
#define DEBUG(x) cerr << #x << " = " << x << endl
#define ll long long
typedef pair <int, int> PII;
typedef unsigned int uint;
typedef unsigned long long ull;
#define i128 __int128
#define fi first
#define se second
mt19937 rnd(chrono::system_clock::now().time_since_epoch().count());
#define ClockA clock_t start, end; start = clock()
#define ClockB end = clock(); cerr << "time = " << double(end - start) / CLOCKS_PER_SEC << "s" << endl;
//#define int long long
inline int rd(){
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
#define rd rd()
void wt(int x){
if (x < 0)
putchar('-'), x = -x;
if (x > 9)
wt(x / 10);
putchar(x % 10 + '0');
return;
}
void wt(char x){
putchar(x);
}
void wt(int x, char k){
wt(x),putchar(k);
}
namespace Star_F{
const int N = 200005;
int n, m, s;
int h[N], e[N << 1], ne[N << 1], w[N << 1], idx;
vector<PII> v[N];
int dis[N];
struct node{
int d, id;
bool friend operator<(node a,node b){
return a.d > b.d;
}
};
void add(int u,int v,int W){
e[++idx] = v, ne[idx] = h[u], w[idx] = W, h[u] = idx;
}
priority_queue<node> q;
void dij(){
memset(dis, 0x3f, sizeof(dis));
dis[s] = 0;
q.push({0, s});
while(!q.empty()){
int d = q.top().d, u = q.top().id;
q.pop();
if(d>dis[u])
continue;
for (int i = h[u]; i;i=ne[i]){
int v = e[i];
if(dis[v]>dis[u]+w[i]){
dis[v] = dis[u] + w[i];
q.push({dis[v], v});
}
}
}
}
void Main(){
cin >> n >> m >> s;
for (int i = 1; i <= m;i++){
int u, v, w;
cin >> u >> v >> w;
add(u, v, w);
}
dij();
for (int i = 1; i <= n;i++)
cout << dis[i] << " ";
}
}
signed main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
ClockA;
int T=1;
// T=rd;
while(T--) Star_F::Main();
// ClockB;
return 0;
}
P5905 【模板】全源最短路(Johnson)
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define ll long long
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
#define ROF(i, a, b) for (int i = (a); i >= (b); --i)
#define DEBUG(x) cerr << #x << '=' << x << endl
inline int rd() {
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
void print(ll x) {
if (x < 0)
putchar('-'), x = -x;
if (x > 9)
print(x / 10);
putchar(x % 10 + '0');
return;
}
namespace Star_F {
struct edge {
int v, w, next;
} e[10005];
struct node {
int dis, id;
bool operator<(const node& a) const { return dis > a.dis; }
node(int d, int x) { dis = d, id = x; }
};
const int INF = 1e9;
int head[5005], vis[5005], t[5005];
int cnt, n, m;
long long h[5005], dis[5005];
void addedge(int u, int v, int w) {
e[++cnt].v = v;
e[cnt].w = w;
e[cnt].next = head[u];
head[u] = cnt;
}
bool spfa(int s) {
queue<int> q;
memset(h, 63, sizeof(h));
h[s] = 0, vis[s] = 1;
q.push(s);
while (!q.empty()) {
int u = q.front();
q.pop();
vis[u] = 0;
for (int i = head[u]; i; i = e[i].next) {
int v = e[i].v;
if (h[v] > h[u] + e[i].w) {
h[v] = h[u] + e[i].w;
if (!vis[v]) {
vis[v] = 1;
q.push(v);
t[v]++;
if (t[v] == n + 1) return false;
}
}
}
}
return true;
}
void dijkstra(int s) {
priority_queue<node> q;
for (int i = 1; i <= n; i++) dis[i] = INF;
memset(vis, 0, sizeof(vis));
dis[s] = 0;
q.push(node(0, s));
while (!q.empty()) {
int u = q.top().id;
q.pop();
if (vis[u]) continue;
vis[u] = 1;
for (int i = head[u]; i; i = e[i].next) {
int v = e[i].v;
if (dis[v] > dis[u] + e[i].w) {
dis[v] = dis[u] + e[i].w;
if (!vis[v]) q.push(node(dis[v], v));
}
}
}
return;
}
void Main() {
n = rd(); m = rd();
for (int i = 1; i <= m; i++) {
int u = rd(), v = rd(), w = rd();
addedge(u, v, w);
}
for (int i = 1; i <= n; i++) addedge(0, i, 0);
if (!spfa(0)) {
cout << -1 << endl;
return;
}
for (int u = 1; u <= n; u++)
for (int i = head[u]; i; i = e[i].next) e[i].w += h[u] - h[e[i].v];
for (int i = 1; i <= n; i++) {
dijkstra(i);
long long ans = 0;
for (int j = 1; j <= n; j++) {
if (dis[j] == INF)
ans += j * INF;
else
ans += j * (dis[j] + h[j] - h[i]);
}
cout << ans << endl;
}
}
}
signed main() {
// freopen(".in", "r", stdin);
// freopen(".out", "w", stdout);
return Star_F::Main(), 0;
}
P3385 【模板】负环
#include <bits/stdc++.h>
using namespace std;
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
#define ROF(i, a, b) for (int i = (a); i >= (b); --i)
#define DEBUG(x) cerr << #x << " = " << x << endl
#define ll long long
typedef pair <int, int> PII;
typedef unsigned int uint;
typedef unsigned long long ull;
#define i128 __int128
#define fi first
#define se second
mt19937 rnd(chrono::system_clock::now().time_since_epoch().count());
#define ClockA clock_t start, end; start = clock()
#define ClockB end = clock(); cerr << "time = " << double(end - start) / CLOCKS_PER_SEC << "s" << endl;
//#define int long long
inline int rd(){
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
#define rd rd()
void wt(int x){
if (x < 0)
putchar('-'), x = -x;
if (x > 9)
wt(x / 10);
putchar(x % 10 + '0');
return;
}
void wt(char x){
putchar(x);
}
void wt(int x, char k){
wt(x),putchar(k);
}
namespace Star_F{
const int N = 2005;
int dis[N], cnt[N];
vector<PII> G[N];
bool vis[N];
int n, m;
bool spfa(){
queue<int> q;
vis[1] = 1, dis[1] = 0, cnt[1] = 1;
q.push(1);
while(!q.empty()){
int u = q.front();
q.pop();
vis[u] = 0;
for (int i = 0; i < G[u].size();i++){
int v = G[u][i].fi, w = G[u][i].se;
if(dis[v]>dis[u]+w){
dis[v] = dis[u] + w;
if(!vis[v]){
cnt[v]++;
q.push(v);
if(cnt[v]>=n)
return true;
}
}
}
}
return false;
}
void Main(){
memset(dis, 0x3f, sizeof(dis));
memset(vis, 0, sizeof(vis));
memset(cnt, 0, sizeof(cnt));
cin >> n >> m;
for (int i = 1; i <= n;i++)
G[i].clear();
for (int i = 1; i <= m;i++){
int u, v, w;
cin >> u >> v >> w;
G[u].push_back({v, w});
if(w>=0)
G[v].push_back({u, w});
}
cout << (spfa() ? "YES" : "NO") << endl;
}
}
signed main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
ClockA;
int T=1;
T=rd;
while(T--) Star_F::Main();
// ClockB;
return 0;
}
P1119 灾后重建
动态加边,动态求全源最短路。
由于输入的时间
注意编号是
#include <bits/stdc++.h>
using namespace std;
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
#define ROF(i, a, b) for (int i = (a); i >= (b); --i)
#define DEBUG(x) cerr << #x << " = " << x << endl
#define ll long long
typedef pair <int, int> PII;
typedef unsigned int uint;
typedef unsigned long long ull;
#define i128 __int128
#define fi first
#define se second
mt19937 rnd(chrono::system_clock::now().time_since_epoch().count());
#define ClockA clock_t start, end; start = clock()
#define ClockB end = clock(); cerr << "time = " << double(end - start) / CLOCKS_PER_SEC << "s" << endl;
//#define int long long
inline int rd(){
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
#define rd rd()
void wt(int x){
if (x < 0)
putchar('-'), x = -x;
if (x > 9)
wt(x / 10);
putchar(x % 10 + '0');
return;
}
void wt(char x){
putchar(x);
}
void wt(int x, char k){
wt(x),putchar(k);
}
namespace Star_F{
const int N = 205;
int T, n, m, a[N], f[N][N];
void update(int k){
for (int i = 0; i < n;i++){
for (int j = 0; j < n;j++)
f[i][j] = f[j][i] = min(f[i][j], f[i][k] + f[k][j]);
}
}
void Main(){
cin >> n >> m;
for (int i = 0; i < n;i++)
cin >> a[i];
memset(f, 0x3f, sizeof(f));
for (int i = 0; i <= n;i++)
f[i][i] = 0;
for (int i = 1; i <= m;i++){
int u, v, w;
cin >> u >> v >> w;
f[u][v] = f[v][u] = w;
}
cin >> T;
int x = 0;
while(T--){
int u, v, t;
cin >> u >> v >> t;
while(a[x]<=t&&x<n)
update(x++);
if(a[u]>t||a[v]>t)
cout << -1 << endl;
else{
if(f[u][v]==0x3f3f3f3f)
cout << -1 << endl;
else
cout << f[u][v] << endl;
}
}
}
}
signed main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
ClockA;
int T=1;
// T=rd;
while(T--) Star_F::Main();
// ClockB;
return 0;
}
P1462 通往奥格瑞玛的道路
看到最大值最小,果断考虑二分。
我们二分一个
如何判断?和最短路类似,我们用 dis[v]=dis[u]-w[i]
更新 dis 数组即可,所以用大根堆维护。
#include <bits/stdc++.h>
using namespace std;
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
#define ROF(i, a, b) for (int i = (a); i >= (b); --i)
#define DEBUG(x) cerr << #x << " = " << x << endl
#define ll long long
typedef pair <int, int> PII;
typedef unsigned int uint;
typedef unsigned long long ull;
#define i128 __int128
#define fi first
#define se second
mt19937 rnd(chrono::system_clock::now().time_since_epoch().count());
#define ClockA clock_t start, end; start = clock()
#define ClockB end = clock(); cerr << "time = " << double(end - start) / CLOCKS_PER_SEC << "s" << endl;
//#define int long long
inline int rd(){
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
#define rd rd()
void wt(int x){
if (x < 0)
putchar('-'), x = -x;
if (x > 9)
wt(x / 10);
putchar(x % 10 + '0');
return;
}
void wt(char x){
putchar(x);
}
void wt(int x, char k){
wt(x),putchar(k);
}
namespace Star_F{
const int N = 10005, M = 100005, INF = 0x3f3f3f3f;
int h[N], ne[M], e[M], w[M], idx;
int n, m, k;
int a[N], l = INF, r, flag;
void add(int u,int v,int W){
e[++idx] = v, ne[idx] = h[u], w[idx] = W, h[u] = idx;
}
int dis[N];
priority_queue<PII> q;
bool check(int mid){
memset(dis, -1, sizeof(dis));
dis[1] = k;
q.push({dis[1], 1});
while(!q.empty()){
int u = q.top().se, d = q.top().fi;
q.pop();
if(dis[u]!=d)
continue;
for (int i = h[u]; i;i=ne[i]){
int v = e[i];
if(a[v]>mid)
continue;
if(dis[v]<dis[u]-w[i]&&dis[u]-w[i]>=0){
dis[v] = dis[u] - w[i];
q.push({dis[v], v});
}
}
}
return dis[n] != -1;
}
void Main(){
cin >> n >> m >> k;
for (int i = 1; i <= n;i++){
cin >> a[i];
l = min(l, a[i]), r = max(r, a[i]);
}
flag = r;
for (int i = 1; i <= m;i++){
int u, v, w;
cin >> u >> v >> w;
add(u, v, w), add(v, u, w);
}
l = a[1];
while(l<=r){
int mid = l + r >> 1;
if(check(mid))
r = mid - 1;
else
l = mid + 1;
}
if(l==flag+1)
cout << "AFK" << endl;
else
cout << l << endl;
}
}
signed main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
ClockA;
int T=1;
// T=rd;
while(T--) Star_F::Main();
// ClockB;
return 0;
}
UVA11090 Going in Cycle!!
经典套路二分题
二分答案
#include <bits/stdc++.h>
using namespace std;
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
#define ROF(i, a, b) for (int i = (a); i >= (b); --i)
#define DEBUG(x) cerr << #x << " = " << x << endl
#define ll long long
typedef pair <int, int> PII;
typedef unsigned int uint;
typedef unsigned long long ull;
#define i128 __int128
#define fi first
#define se second
mt19937 rnd(chrono::system_clock::now().time_since_epoch().count());
#define ClockA clock_t start, end; start = clock()
#define ClockB end = clock(); cerr << "time = " << double(end - start) / CLOCKS_PER_SEC << "s" << endl;
//#define int long long
inline int rd(){
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
#define rd rd()
void wt(int x){
if (x < 0)
putchar('-'), x = -x;
if (x > 9)
wt(x / 10);
putchar(x % 10 + '0');
return;
}
void wt(char x){
putchar(x);
}
void wt(int x, char k){
wt(x),putchar(k);
}
namespace Star_F{
const int INF = 0x3f3f3f3f;
const int N = 305, M = 15000;
int m, n;
int h[N], e[M], ne[M], idx;
double w[M];
int tmp = 1;
void add(int u,int v,double W){
e[++idx] = v, ne[idx] = h[u], w[idx] = W, h[u] = idx;
}
int nm[N], vis[N];
double dis[N];
bool spfa(double x){
queue<int> q;
memset(vis, 1, sizeof(vis));
for (int i = 1; i <= n;i++)
dis[i] = (double)INF;
memset(nm, 0, sizeof(nm));
for (int i = 1; i <= m;i++)
w[i] -= x;
for (int i = 1; i <= n;i++)
q.push(i);
while(!q.empty()){
int now = q.front();
q.pop();
vis[now] = 0;
for (int i = h[now]; i;i=ne[i]){
int v=e[i];
if(dis[v]>=dis[now]+w[i]){
dis[v] = dis[now] + w[i];
nm[v] = nm[now] + 1;
if(vis[v]==0){
q.push(v);
}
if(nm[v]>=n+1){
for (int i = 1; i <= m;i++)
w[i] += x;
return 1;
}
}
}
}
for (int i = 1; i <= m;i++) w[i]+=x;
return 0;
}
void Main(){
idx = 0;
memset(h, 0, sizeof(h));
cin >> n >> m;
for (int i = 1; i <= m;i++){
int u, v, w;
cin >> u >> v >> w;
add(u, v, (double)w);
}
double l = 0, r = 100000001;
while(r-l>0.0000001){
double mid = (l + r) / 2;
if(spfa(mid))
r = mid;
else l = mid;
}
cout << "Case #" << tmp++ << ": ";
if(r==100000001)
cout << "No cycle found." << endl;
else
printf("%.2lf\n", l);
}
}
signed main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
ClockA;
int T=1;
T=rd;
while(T--) Star_F::Main();
// ClockB;
return 0;
}
P2865 [USACO06NOV] Roadblocks G
单源次短路模板题目
#include <bits/stdc++.h>
using namespace std;
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
#define ROF(i, a, b) for (int i = (a); i >= (b); --i)
#define DEBUG(x) cerr << #x << " = " << x << endl
#define ll long long
typedef pair <int, int> PII;
typedef unsigned int uint;
typedef unsigned long long ull;
#define i128 __int128
#define fi first
#define se second
mt19937 rnd(chrono::system_clock::now().time_since_epoch().count());
#define ClockA clock_t start, end; start = clock()
#define ClockB end = clock(); cerr << "time = " << double(end - start) / CLOCKS_PER_SEC << "s" << endl;
//#define int long long
inline int rd(){
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
#define rd rd()
void wt(int x){
if (x < 0)
putchar('-'), x = -x;
if (x > 9)
wt(x / 10);
putchar(x % 10 + '0');
return;
}
void wt(char x){
putchar(x);
}
void wt(int x, char k){
wt(x),putchar(k);
}
namespace Star_F{
const int N=200005;
int n, m;
int h[N], e[N], ne[N], w[N], idx;
int dis[2][N];
void add(int u,int v,int W){
e[++idx] = v, ne[idx] = h[u], w[idx] = W, h[u] = idx;
}
struct node{
int id, d;
bool friend operator<(node a,node b){
return a.d > b.d;
}
};
priority_queue<node> q;
void dij(){
for (int i = 1; i <= n;i++)
dis[0][i] = dis[1][i] = 2147483647;
dis[0][1] = 0;
q.push({1, 0});
while(!q.empty()){
int u = q.top().id, d = q.top().d;
q.pop();
if(d>dis[1][u])
continue;
for (int i = h[u]; i;i=ne[i]){
int v = e[i];
if(dis[0][v]>d+w[i]){
dis[1][v] = dis[0][v];
dis[0][v] = d + w[i];
q.push({v, dis[0][v]});
}
if(dis[1][v]>d+w[i]&&dis[0][v]<d+w[i]){
dis[1][v] = d + w[i];
q.push({v, dis[1][v]});
}
}
}
}
void Main(){
cin >> n >> m;
for (int i = 1; i <= m;i++){
int u, v, w;
cin >> u >> v >> w;
add(u, v, w), add(v, u, w);
}
dij();
cout << dis[1][n] << endl;
}
}
signed main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
ClockA;
int T=1;
// T=rd;
while(T--) Star_F::Main();
// ClockB;
return 0;
}
P1875 佳佳的魔法药水
最短路计数问题。
#include <bits/stdc++.h>
using namespace std;
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
#define ROF(i, a, b) for (int i = (a); i >= (b); --i)
#define DEBUG(x) cerr << #x << " = " << x << endl
#define ll long long
typedef pair <int, int> PII;
typedef unsigned int uint;
typedef unsigned long long ull;
#define i128 __int128
#define fi first
#define se second
mt19937 rnd(chrono::system_clock::now().time_since_epoch().count());
#define ClockA clock_t start, end; start = clock()
#define ClockB end = clock(); cerr << "time = " << double(end - start) / CLOCKS_PER_SEC << "s" << endl;
//#define int long long
inline int rd(){
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
#define rd rd()
void wt(int x){
if (x < 0)
putchar('-'), x = -x;
if (x > 9)
wt(x / 10);
putchar(x % 10 + '0');
return;
}
void wt(char x){
putchar(x);
}
void wt(int x, char k){
wt(x),putchar(k);
}
namespace Star_F{
const int N = 3005;
int c[N], ans[N], t[N][N];
bool f[N];
void Main(){
int n;
cin >> n;
for (int i = 1; i <= n;i++)
cin >> c[i], ans[i] = 1;
int u, v, w;
while(scanf("%d%d%d",&u,&v,&w)!=EOF)
t[u + 1][v + 1] = t[v + 1][u + 1] = w + 1;
for (int i = 1; i < n;i++){
int maxn = 0x3f3f3f3f;
int b;
for (int j = 1; j <= n;j++)
if(!f[j]&&c[j]<maxn)
b = j, maxn = c[j];
f[b] = 1;
for (int j = 1; j <= n;j++)
if(f[j]&&t[b][j]){
if(c[b]+c[j]==c[t[b][j]])
ans[t[b][j]] += ans[b] * ans[j];
if(c[b]+c[j]<c[t[b][j]])
c[t[b][j]] = c[b] + c[j], ans[t[b][j]] = ans[b] * ans[j];
}
}
cout << c[1] << " " << ans[1] << endl;
}
}
signed main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
ClockA;
int T=1;
// T=rd;
while(T--) Star_F::Main();
// ClockB;
return 0;
}
P1948 [USACO08JAN] Telephone Lines S
最大值最小,还是考虑二分。
二分
当然更优秀的做法是 01BFS
。
#include <bits/stdc++.h>
using namespace std;
const int N = 1010, M = 20010;
int n, m, k;
int h[N], e[M], w[M], ne[M], idx;
int dist[N];
deque<int> q;
bool st[N];
void add(int a, int b, int c){
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}
bool check(int bound){
memset(dist, 0x3f, sizeof dist);
memset(st, 0, sizeof st);
q.push_back(1);
dist[1] = 0;
while (q.size()){
int t = q.front();
q.pop_front();
if (st[t]) continue;
st[t] = true;
for (int i = h[t]; ~i; i = ne[i]){
int j = e[i], x = w[i] > bound;
if (dist[j] > dist[t] + x){
dist[j] = dist[t] + x;
if (!x) q.push_front(j);
else q.push_back(j);
}
}
}
return dist[n] <= k;
}
int main(){
cin >> n >> m >> k;
memset(h, -1, sizeof h);
while (m -- ){
int a, b, c;
cin >> a >> b >> c;
add(a, b, c), add(b, a, c);
}
int l = 0, r = 1e6 + 1;
while (l < r){
int mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
if (r == 1e6 + 1) cout << -1 << endl;
else cout << r << endl;
return 0;
}
P2371 [国家集训队] 墨墨的等式
奇妙好题!!
同余最短路:与差分约束有异曲同工之妙,都将约束条件转化为边,每种状态转化为点。把本来与图论毫不相干的问题抽象到具体的图上,通过拓扑排序,最短路等基础算法获得最小状态,从而解决问题。
在本题中,以
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
#define ROF(i, a, b) for (int i = (a); i >= (b); --i)
#define DEBUG(x) cerr << #x << '=' << x << endl
inline int rd()
{
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
void print(int x)
{
if (x < 0)
putchar('-'), x = -x;
if (x > 9)
print(x / 10);
putchar(x % 10 + '0');
return;
}
namespace Star_F
{
#define int long long
const int maxn = 13, N = 5e5 + 10, M = 11 * 5e5 + 10;
int n, l, r;
int a[maxn];
struct edge
{
int u, v, w, nxt;
} e[M];
int tot, head[N];
void add(int u, int v, int w) { e[++tot] = {u, v, w, head[u]}, head[u] = tot; }
struct node
{
int u, dis;
bool operator<(const node &a) const { return dis > a.dis; }
};
int vis[N], dis[N];
void init() {
FOR(i, 1, N - 1)
dis[i] = 1e18 + 10,
vis[i] = 0;
}
void dj(int s)
{
init();
dis[s] = 0;
priority_queue<node> q;
q.push({s, dis[s]});
while (!q.empty())
{
int u = q.top().u, k = q.top().dis;
q.pop();
if (vis[u] && k != dis[u])
continue;
vis[u] = 1;
for (int i = head[u]; i; i = e[i].nxt)
{
int v = e[i].v, w = e[i].w;
if (dis[v] > dis[u] + w)
{
dis[v] = dis[u] + w;
q.push({v, dis[v]});
}
}
}
}
int minn = 1e18 + 10, id = 0;
int sov(int x)
{
int ans = 0;
FOR(i, 0, minn - 1)
{
if (dis[i] <= x)
{
ans += (x - dis[i]) / minn + 1;
}
}
return ans;
}
void Main()
{
cin >> n >> l >> r;
FOR(i, 1, n)
{
cin >> a[i];
if (a[i] == 0)
{
i--;
n--;
continue;
}
if (minn > a[i])
minn = a[i], id = i;
}
FOR(i, 0, minn - 1)
{
FOR(j, 1, n)
{
if (a[j] == minn)
continue;
add(i, (i + a[j]) % minn, a[j]);
}
}
dj(0);
int ans = sov(r) - sov(l - 1);
cout << ans;
}
}
signed main(){
//freopen("inq.in","r",stdin);
//freopen("inq.out","w",stdout);
return Star_F::Main(), 0;
return 0;
}
P2446 [SDOI2010] 大陆争霸
由题可知,有的城市被保护。设
设
#include <bits/stdc++.h>
using namespace std;
const int N=3001,M=200001;
struct edge{
int u,nxt,v;
}e[M];
int he[N],n,m,tote;
struct Graph{
int u,nxt;
}G[M];
int hg[N],totg;
struct node{
int key,len;
friend bool operator < (node x,node y){
return x.len<y.len;
}
};
int dis[N],into[N],in[N],arr[N];
bool vis[N];
priority_queue<node> q;
void dijkstra(int s){
for(int i=1;i<=n;i++)
dis[i]=arr[i]=1e9;
dis[s]=into[s]=arr[s]=0;
in[s]=0;
q.push({s,0});
int u,v;
while(!q.empty()){
u=q.top().key;
q.pop();
if(vis[u]) continue;
vis[u]=1;
for(int k=he[u];k;k=e[k].nxt){
v=e[k].u;
if(dis[u]+e[k].v<arr[v]){
arr[v]=dis[u]+e[k].v;
if(!in[v]){
dis[v]=max(into[v],arr[v]);
q.push({v,-dis[v]});
}
}
}
for(int k=hg[u];k;k=G[k].nxt){
v=G[k].u;
into[v]=max(into[v],dis[u]);
in[v]--;
if(!in[v]){
dis[v]=max(into[v],arr[v]);
q.push({v,-dis[v]});
}
}
}
}
int main(){
cin >> n >> m;
while(m--){
int x,y,l;
cin >> x >> y >> l;
e[++tote].u = y, e[tote].nxt = he[x], e[tote].v = l, he[x] = tote;
}
for(int i=1;i<=n;i++){
int x, y;
cin >> x;
while(x--){
cin >> y;
++in[i], G[++totg].u = i, G[totg].nxt = hg[y], hg[y] = totg;
}
}
dijkstra(1);
cout << dis[n] << endl;
return 0;
}
P8817 [CSP-S 2022] 假期计划
-
和 之间可达意为 和 之间可以不多于 次转车到达,及 , 的距离不多于 。 -
一个点
在家附近,意为 和 1 之间可达。
注意,为方便,特殊地,我们认为自己和自己不可达。
观察数据范围,
注意:对于满足边权全为 1 的图,单源最短路可以做到
的复杂度(采用 BFS); 对于满足边权只有 0,1 两种的图,单源最短路也可以做到
的复杂度(采用 0-1 BFS)。
我们考虑一条
很直接的想法是,依次考虑
但有一种贪心是对的,那就是确定了
由于环的对称性,可以发现确定了
有了大体思路。
我们定义
第一步:我们预处理出
第二步:直接
发现重复性的细节是存在问题的,比如:会出现
不过,贪心思想还是不变的:
更换定义,
当发现
当发现
发现并没有完全解决:如果这样处理后的
还是贪心思想,考虑把
重复性解决了,但是还有个细节:如果原先
至于原先
如果直接这么写是没有问题的,但是麻烦了。下面是一种更好写的处理方法:
直接分别枚举
需要提前预处理出
注意某些点可达,还在家附近的点数可能没有 3 个,因此注意类似访问
如果枚举到某个
题目保证全局上是有解的。
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 2510, M = 20010;
int n, m, k;
LL w[N];
int h[N], e[M], ne[M], idx;
int dist[N], f[N][4], q[N];
bool st[N][N];
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
void bfs(int start, int f[])
{
int hh = 0, tt = 0;
memset(dist, 0x3f, sizeof dist);
dist[start] = 0;
q[0] = start;
while (hh <= tt)
{
int t = q[hh ++ ];
if (dist[t] == k + 1) continue;
for (int i = h[t]; ~i; i = ne[i])
{
int j = e[i];
if (dist[j] > dist[t] + 1)
{
dist[j] = dist[t] + 1;
st[start][j] = true;
q[ ++ tt] = j;
if (st[1][j])
{
f[3] = j;
for (int u = 3; u; u -- )
if (w[f[u]] > w[f[u - 1]])
swap(f[u], f[u - 1]);
else break;
}
}
}
}
}
int main()
{
scanf("%d%d%d", &n, &m, &k);
for (int i = 2; i <= n; i ++ ) scanf("%lld", &w[i]);
memset(h, -1, sizeof h);
while (m -- )
{
int a, b;
scanf("%d%d", &a, &b);
add(a, b), add(b, a);
}
for (int i = 1; i <= n; i ++ )
bfs(i, f[i]);
LL res = 0;
for (int b = 2; b <= n; b ++ )
for (int c = 2; c <= n; c ++ )
if (st[b][c])
for (int x = 0; x < 3; x ++ )
for (int y = 0; y < 3; y ++ )
{
int a = f[b][x], d = f[c][y];
if (a && d && a != d && a != c && b != d)
res = max(res, w[a] + w[b] + w[c] + w[d]);
}
printf("%lld\n", res);
return 0;
}
__EOF__
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 本地部署 DeepSeek:小白也能轻松搞定!
· 如何给本地部署的DeepSeek投喂数据,让他更懂你
· 从 Windows Forms 到微服务的经验教训
· 李飞飞的50美金比肩DeepSeek把CEO忽悠瘸了,倒霉的却是程序员
· 超详细,DeepSeek 接入PyCharm实现AI编程!(支持本地部署DeepSeek及官方Dee