[UVa10296]Jogging Trails

题目大意:
  中国邮递员问题。
  给你一个无向带权连通图,求经过所有边并返回起点的最短路径。

思路:
  Edmonds-Johnson算法。
  显然,当原图为欧拉图时,答案即为其欧拉回路的长度。
  考虑原图不存在欧拉回路时的情况。
  一个图存在欧拉回路,当且仅当这个图中度为奇数的点的个数为0。
  然而现在我们的图并不一定是欧拉图,这就说明图中有可能由度数为奇数的点。
  显然,我们需要重复走的边,一定是连接这些度为奇数的点的。
  我们可以用Dijkstra对这些点求最短路(由于数据范围较小,用Floyd也没关系)。
  然后对所有点对之间的最短路构建新图。
  再对新图跑一般图最小权完美匹配(用状压DP或者记忆化搜索)。
  最后匹配出来的匹配就是重复走的路径长度。
  用老图的边权和加上新图的匹配就是答案。
  本来能1A的,但是由于用了平板电视,在POJ上CE了,但是在UVa上就直接0ms0kB过。

  1 #include<cstdio>
  2 #include<cctype>
  3 #include<vector>
  4 #include<cstring>
  5 #include<functional>
  6 #include<ext/pb_ds/priority_queue.hpp>
  7 inline int getint() {
  8     register char ch;
  9     while(!isdigit(ch=getchar()));
 10     register int x=ch^'0';
 11     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
 12     return x;
 13 }
 14 const int inf=0x7fffffff;
 15 const int V=16;
 16 struct Edge {
 17     int to,w;
 18 };
 19 std::vector<Edge> e[V];
 20 void add_edge(const int &u,const int &v,const int &w) {
 21     e[u].push_back((Edge){v,w});
 22     e[v].push_back((Edge){u,w});
 23 }
 24 int deg[V];
 25 std::vector<int> kv;
 26 struct Vertex {
 27     int d,id;
 28     bool operator > (const Vertex &another) const {
 29         return d>another.d;
 30     }
 31 };
 32 int n;
 33 int k[V][V];
 34 __gnu_pbds::priority_queue<Vertex,std::greater<Vertex> > q;
 35 __gnu_pbds::priority_queue<Vertex,std::greater<Vertex> >::point_iterator p[V];
 36 inline void Dijkstra(const int &s) {
 37     int *d=k[s];
 38     q.clear();
 39     for(register int i=1;i<=n;i++) {
 40         if(i!=s) {
 41             p[i]=q.push((Vertex){d[i]=inf,i});
 42         } else {
 43             p[i]=q.push((Vertex){d[i]=0,i});
 44         }
 45     }
 46     while(q.top().d!=inf) {
 47         const int x=q.top().id;
 48         for(register unsigned i=0;i<e[x].size();i++) {
 49             const int &y=e[x][i].to;
 50             if(d[x]+e[x][i].w<d[y]) {
 51                 d[y]=d[x]+e[x][i].w;
 52                 q.modify(p[y],(Vertex){d[y],y});
 53             }
 54         }
 55         q.modify(p[x],(Vertex){inf,x});
 56     }
 57 }
 58 int f[1<<16];
 59 inline void init() {
 60     for(register int i=1;i<V;i++) {
 61         e[i].clear();
 62     }
 63     kv.clear();
 64     memset(deg,0,sizeof deg);
 65     memset(f,-1,sizeof f);
 66 }
 67 int dfs(const int st) {
 68     if(!st) return 0;
 69     if(~f[st]) return f[st];
 70     f[st]=inf;
 71     for(int i=1;i<=n;i++) {
 72         if(!(st&(1<<i))) continue;
 73         for(int j=1;j<=n;j++) {
 74             if(i==j) continue;
 75             if(!(st&(1<<j))) continue;
 76             f[st]=std::min(f[st],dfs(st^(1<<i)^(1<<j))+k[i][j]);
 77         }
 78     }
 79     return f[st];
 80 }
 81 int main() {
 82     for(;;) {
 83         n=getint();
 84         if(!n) return 0;
 85         init();
 86         int m=getint();
 87         int ans=0;
 88         for(register int i=0;i<m;i++) {
 89             const int &u=getint(),&v=getint(),&w=getint();
 90             deg[u]++,deg[v]++;
 91             add_edge(u,v,w);
 92             ans+=w;
 93         }
 94         int st=0;
 95         for(register int i=1;i<=n;i++) {
 96             if(deg[i]&1) {
 97                 kv.push_back(i);
 98                 st|=1<<i;
 99             }
100         }
101         for(register unsigned i=0;i<kv.size();i++) {
102             Dijkstra(kv[i]);
103         }
104         ans+=dfs(st);
105         printf("%d\n",ans);
106     }
107 }

 

posted @ 2017-09-26 10:33  skylee03  阅读(501)  评论(0编辑  收藏  举报