洛谷P6175 无向图的最小环问题
题目传送门
题目大意
求无向图的最小环,\(1\leq n\leq 100\),\(1\leq m\leq5 \times 10^{3}\),\(1\leq d\leq 10^{5}(n\)为顶点数,\(m\)为边数,\(d\)为边权\()\)。
Solution1
Floyd求最小环
时间复杂度\(O(n^3)\)
设一个环中编号最大的顶点为\(k\),则这个环的权值和可表示为\(d[i][j]+w[i][k]+w[k][j]\),\(i\)、\(j\)为环中与\(k\)相邻的顶点,\(d[i][j]\)表示\(i\)到\(j\)不经过\(k\)的最短路长度。
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
template<typename T>void read(T& x){
int f=0;x=0;char ch=getchar();
while(ch<'0'||ch>'9'){f|=(ch=='-');ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+(ch^48);ch=getchar();}
if(f)x=-x;
}
int n,m,ans=INF;
int w[105][105],d[105][105];
int main(){
int u,v,ww;
read(n),read(m);
memset(d,INF,sizeof(d));
memset(w,INF,sizeof(w));
for(int i=1;i<=n;++i)d[i][i]=0;
for(int i=1;i<=m;++i){
read(u),read(v),read(ww);
d[u][v]=d[v][u]=w[u][v]=w[v][u]=min(w[u][v],ww);//处理重边
}
for(int k=1;k<=n;++k){
for(int i=1;i<k;++i)
for(int j=1;j<k;++j)
if(i!=j&&d[i][j]!=INF&&w[i][k]!=INF&&w[k][j]!=INF&&d[i][j]+w[i][k]+w[k][j]<ans)//注意要i!=j,否则构不成环
ans=d[i][j]+w[i][k]+w[k][j];//此处的d[i][j]表示从i到j不经过k的最短路长度
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
}
if(ans<INF)printf("%d",ans);
else printf("No solution.");
return 0;
}
Solution2
Dijkstra
时间复杂度\(O(m^2logm)\)\((\)实际上跑不满,剪枝后很快\()\)
枚举边\(i-j\),环和即为\(d[i][j]+w[i][j]\),用\(Dijkstra\)求\(d[i][j]\)。
要记得剪枝,否则会\(TLE\)
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
template<typename T>void read(T&x){
int f=0;x=0;char ch=getchar();
while(ch<'0'||ch>'9'){f|=(ch=='-');ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+(ch^48);ch=getchar();}
if(f)x=-x;
}
int n,m,ans=INF;
int w[105][105],d[105],vis[105];
int u[5005],v[5003];
struct node{
int d,x;
node(int d,int x):d(d),x(x){}
bool operator < (const node& a)const{
return d>a.d;
}
};
int dij(int s,int t){
priority_queue<node>q;
memset(d,INF,sizeof(d));
memset(vis,0,sizeof(vis));
d[s]=0;
q.push(node(0,s));
while(!q.empty()){
node u=q.top();q.pop();
if(vis[u.x])continue;
vis[u.x]=1;
if(d[u.x]+w[s][t]>ans)continue;//要剪枝
for(int i=1;i<=n;++i){
if((u.x!=s||i!=t)&&(u.x!=t||i!=s)&&w[u.x][i]!=INF&&d[i]>d[u.x]+w[u.x][i]){//不能经过s-t这条边
d[i]=d[u.x]+w[u.x][i];
q.push(node(d[i],i));
}
}
}
return d[t];
}
int main(){
int u1,v1,ww;
read(n),read(m);
memset(w,INF,sizeof(w));
for(int i=1;i<=m;++i){
read(u1),read(v1),read(ww);
u[i]=u1;
v[i]=v1;
w[u1][v1]=w[v1][u1]=min(w[u1][v1],ww);//处理重边
}
for(int i=1;i<=m;++i){
int temp=dij(u[i],v[i]);
if(temp!=INF)
ans=min(ans,temp+w[u[i]][v[i]]);
}
if(ans!=INF)printf("%d",ans);
else printf("No solution.");
return 0;
}

浙公网安备 33010602011771号