题目描述:给出n个点m条边的无向图,求出对于任意两点之间的所有最短路覆盖的边数。
题目解析:首先题目数据范围较小,有500左右的点,首先可以用floyd预处理出任意两点之间的最短路,然后用 dp[i][j]表示有多少条与i相邻的边位于从i到j的最短路径上,计算出指向j的边中在从i到j最短路上的个数,最后统计这条路径上总共有多少条边,枚举k就能得到结果。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
#define eps 1e-5
template<class T> void read(T&num) {
char CH; bool F=false;
for(CH=getchar();CH<'0'||CH>'9';F= CH=='-',CH=getchar());
for(num=0;CH>='0'&&CH<='9';num=num*10+CH-'0',CH=getchar());
F&&(num=-num);
}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
int lowbit(int x){return x&(-x);}
const int maxn=500+100;
const int inf=0x3f3f3f3f;
const ll mod=1e9+7;
int n,m;
int dis[maxn][maxn],mp[maxn][maxn],dp[maxn][maxn];
void floyd(){
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
int main(){
read(n);
read(m);
memset(mp,inf,sizeof mp);
memset(dis,0,sizeof dis);
memset(dp,0,sizeof dp);
while(m--){
int u,v,w;
read(u);read(v);read(w);
mp[u][v]=mp[v][u]=w;
}
memcpy(dis,mp,sizeof mp);
for(int i=1;i<=n;i++) dis[i][i]=0;
floyd();
for(int i=1;i<=n;i++){
for(int k=1;k<=n;k++){
for(int j=1;j<=n;j++){
if(mp[i][k]!=inf&&dis[i][j]==dis[k][j]+mp[i][k]){
dp[i][j]++;
}
}
}
}
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
int ans=0;
for(int k=1;k<=n;k++){
if(dis[i][j]==dis[i][k]+dis[k][j]) ans+=dp[k][j];
}
printf("%d%c",ans,"\n "[i!=n-1]);
}
}
}
题目大意:有n个屋子和1只老鼠,老鼠会从第i间房子跑到ai 间房子。在每间房子放捕鼠夹都有代价wi,而老鼠的初始位置可能是任何一个房间,为了保证抓到老鼠你需要在若干房间放上捕鼠夹,求最小代价和。
题目解析:简单来说就是有n个点,n条边的图。我们需要对这个图中的环进行分析,只需要取这个环中的最小值,就是答案。所以这道题有多种解法,比如使用tarjan把每个强连通分量缩点,把留下的最小wi相加就是答案。或者使用dfs找环,同时判断环内最小的wi。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
#define eps 1e-5
template<class T> void read(T&num) {
char CH; bool F=false;
for(CH=getchar();CH<'0'||CH>'9';F= CH=='-',CH=getchar());
for(num=0;CH>='0'&&CH<='9';num=num*10+CH-'0',CH=getchar());
F&&(num=-num);
}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
int lowbit(int x){return x&(-x);}
const int maxn=3e5+100;
const int inf=0x3f3f3f3f;
const ll mod=1e9+7;
int n;
int w[maxn],vis[maxn],sum=0;
int a[maxn];
int dfs(int x,int fa){
if(vis[x]) return inf;
vis[x]=fa;
int y=a[x],minn=inf;
if(vis[y]==fa){
minn=min(w[x],minn);
int k=a[x];
while(k!=x){
minn=min(w[k],minn);
k=a[k];
}
return minn;
}
return dfs(a[x],fa);
}
int main(){
read(n);
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++) read(w[i]);
for(int i=1;i<=n;i++) read(a[i]);
for (int i=1;i<=n;i++){
int k=dfs(i,i);
if(k<inf) sum+=k;
}
printf("%d\n",sum);
return 0;
}