uva 12544 无向图最小环
思路:这题的N有500,直接floyd肯定超时。
我的做法是每次枚举一个点,求出包含这个点的最小环。
对所有最小环取最小值。求包含某个点的最小环我用的是启发式搜索,先以该点求一次spfa,然后dfs解决问题。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define Maxn 600 #define inf 1000000 using namespace std; int head[Maxn],vi[Maxn],dis[Maxn],e,que[Maxn*100],ans,dist[Maxn]; struct Edge{ int u,v,next; }edge[Maxn*100]; void init() { memset(head,-1,sizeof(head)); memset(vi,0,sizeof(vi)); e=0; } void add(int u,int v) { edge[e].u=u,edge[e].v=v,edge[e].next=head[u],head[u]=e++; edge[e].u=v,edge[e].v=u,edge[e].next=head[v],head[v]=e++; } void spfa(int u) { int i,j,v,now,rear,he; for(i=0;i<Maxn;i++){ dist[i]=inf; vi[i]=0; } dist[u]=0; he=rear=0; que[he++]=u; while(he!=rear){ now=que[rear++]; vi[now]=0; for(i=head[now];i!=-1;i=edge[i].next){ v=edge[i].v; if(v==now) continue; if(dist[now]+1<dist[v]){ dist[v]=dist[now]+1; if(!vi[v]){ que[he++]=v; vi[v]=1; } } } } return ; } void dfs(int u,int pre) { int i,v; for(i=head[u];i!=-1;i=edge[i].next){ v=edge[i].v; if(v==pre) continue; if(dis[v]==0){ ans=min(ans,dis[u]+1); continue; } if(dis[u]+dist[u]>=ans) return ; if(dis[u]+1<dis[v]){ dis[v]=dis[u]+1; dfs(v,u); } } } int main() { int n,m,i,j,u,v,t,Ca=0; scanf("%d",&t); while(t--){ init(); scanf("%d%d",&n,&m); for(i=1;i<=m;i++){ scanf("%d%d",&u,&v); u++,v++; add(u,v); } ans=inf; for(i=1;i<=n;i++){ for(j=0;j<=n;j++) dis[j]=inf; dis[i]=0; spfa(i); dfs(i,0); } printf("Case %d: ",++Ca); if(ans>=inf) printf("impossible\n"); else printf("%d\n",ans); } return 0; }