洛谷 P1841 [JSOI2007] 重要的城市 做題記錄

coding_goat_qwq發表於2024-11-22

前置芝士:floyd,組合數學

思路

因為要所有點的距離不變,所以我們需要一個全源最短路演算法,理所當然的用上了 floyd(下文迴圈順序預設為 \(k,i,j\))。
我們在記錄最短路長度的時候,同時記錄最短路的數量 \(sum\)
最後我們列舉所有三個點組成的三元組,如果有 \(i\to k\to j\) 的最短路,且有 \(i\to j\) 的最短路數量正好是 \((i \to k )\times( k \to j)\) 的數量,那麼就證明,\(i\to j\) 一定會經過 \(k\),故 \(k\) 是關鍵點。
時間複雜度:\(O(n^3)\)
難點/坑點:注意自已到自己再到其它城市是不可行的,所以要記得在跑完 floyd 後將 \(f_{i,i}=\inf\)

點選檢視程式碼
#include<bits/stdc++.h>

#define ll long long
#define i128 __int128

#define mem(a,b) memset((a),(b),sizeof(a))
#define m0(a) memset((a),0,sizeof(a))
#define m1(a) memset(a,-1,sizeof(a))
#define lb(x) ((x)&-(x))
#define lc(x) ((x)<<1)
#define rc(x) (((x)<<1)|1)
#define pb(G,x) (G).push_back((x))
#define For(a,b,c) for(int a=(b);a<=(c);a++)
#define Rep(a,b,c) for(int a=(b);a>=(c);a--)
#define in1(a) a=read()
#define in2(a,b) a=read(), b=read()
#define in3(a,b,c) a=read(), b=read(), c=read()

using namespace std;

int read() {
	int x=0,f=1; char c=getchar();
	for(;c<'0'||c>'9';c=getchar()) f=(c=='-'?-1:1); 
	for(;c<='9'&&c>='0';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
	return x*f;
}
void write(int x) { if(x>=10) write(x/10); putchar('0'+x%10); }

const int mod = 998244353;
int qpo(int a,int b) {int res=1; for(;b;b>>=1,a=(a*a)%mod) if(b&1) res=res*a%mod; return res; }
int inv(int a) {return qpo(a,mod-2); }

#define maxn 205
int n,m;
int f[maxn][maxn],sum[maxn][maxn];
void work() {
	in2(n,m);
	mem(f,0x3f);
	For(i,1,m) {
		int u,v,d;
		in3(u,v,d);
		f[u][v]=f[v][u]=min(f[u][v],d);
		sum[u][v]=1;sum[v][u]=1;
	}
	For(k,1,n) For(i,1,n) For(j,1,n)
		if(f[i][k]+f[k][j]<f[i][j])
			f[i][j]=f[i][k]+f[k][j],
			sum[i][j]=sum[i][k]*sum[k][j];
		else if(f[i][j]==f[i][k]+f[k][j])
			sum[i][j]+=sum[i][k]*sum[k][j];
	int flg=0;
	For(i,1,n) f[i][i]=1e9;
	For(k,1,n) {
		int fin=0;
		For(i,1,n){
			For(j,1,n)
				if(!fin&&f[i][j]==f[i][k]+f[k][j]&&sum[i][j]==sum[i][k]*sum[k][j])
				{
					cout<<k<<' ';
					fin=1;
					flg=1; break;
				}
			if(fin) break;
		}
	}
	if(!flg) return cout<<"No important cities.",void();
}

signed main() {
//	ios::sync_with_stdio(false); 
//	cin.tie(0); cout.tie(0);
	int _=1;
//	int _=read();
	For(i,1,_) {
		work();
	}
	return 0;
}