题意:求无向图最小环(n<=8000,m<=4000)
动态把边加进去跑Dij,在加入一条边(u,v,c)之前,先求出mindis(u,v),更新答案ans=min(ans,mindis(u,v)+c),复杂度$O(m^2logn)$
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef double db; 5 const int N=8000+10,inf=0x3f3f3f3f; 6 int n,m,d[N],hd[N],ne,ka; 7 struct E {int v,c,nxt;} e[N]; 8 void link(int u,int v,int c) {e[ne]= {v,c,hd[u]},hd[u]=ne++;} 9 struct P { 10 int x,y; 11 bool operator<(const P& b)const {return x!=b.x?x<b.x:y<b.y;} 12 }; 13 map<P,int> p2id; 14 int id(P p) { 15 if(p2id.count(p))return p2id[p]; 16 n=p2id.size()+1; 17 return p2id[p]=n; 18 } 19 struct D { 20 int u,g; 21 bool operator<(const D& b)const {return g>b.g;} 22 }; 23 priority_queue<D> q; 24 void upd(int u,int g) {if(d[u]>g)d[u]=g,q.push({u,g});} 25 int Dij(int S,int T) { 26 while(q.size())q.pop(); 27 for(int i=1; i<=n; ++i)d[i]=inf; 28 upd(S,0); 29 while(q.size()) { 30 int u=q.top().u,g=q.top().g; 31 q.pop(); 32 if(g!=d[u])continue; 33 if(u==T)return g; 34 for(int i=hd[u]; ~i; i=e[i].nxt) { 35 int v=e[i].v; 36 upd(v,g+e[i].c); 37 } 38 } 39 return inf; 40 } 41 42 int main() { 43 int _; 44 for(scanf("%d",&_); _--;) { 45 int ans=inf; 46 n=0; 47 memset(hd,-1,sizeof hd),ne=0; 48 p2id.clear(); 49 scanf("%d",&m); 50 while(m--) { 51 int x1,x2,y1,y2,c; 52 scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&c); 53 int u=id({x1,y1}),v=id({x2,y2}); 54 ans=min(ans,Dij(u,v)+c); 55 link(u,v,c),link(v,u,c); 56 } 57 printf("Case #%d: %d\n",++ka,ans==inf?0:ans); 58 } 59 return 0; 60 }