UVA-12118 Inspector's Dilemma

欧拉回路+dfs
任意两点之间都有连通,要输出经过所有给出的边的最小时间
要使经过所有所给边的时间最小,一定不会将一个边走过两次,这样就变成
了构造一个欧拉道路的问题,输入也许有多个连通块,所以每个连通块都要
构造成一个欧拉道路(回路),通过度数统计需要增加的边,再加上连接不同
连通快的边,再加上所给出的边就是答案。
跑了500多ms,挺长的,个人感觉是因为样例中有大量的稀疏图,邻接矩阵浪费了大量时间,改成邻接表
应该会快点。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<set>
 5 #define inf 0x7f7f7f7f
 6 #define mem(a) memset(a,0,sizeof(a))
 7 #define rep(i,n) for(int i=0;i<n;i++)
 8 using namespace std;
 9 const int maxn = 1010;
10 int G[maxn][maxn];
11 int vis[maxn];
12 int v,e,t;
13 int ans; int degree[maxn];
14 int dfs(int n){
15     for(int i=1;i<=v;i++){
16         if(G[n][i]){
17             degree[n]++;
18             degree[i]++;
19             G[n][i]=G[i][n]=0;
20             ans++;//printf("%d
",ans);
21             dfs(i);
22         }
23     }
24 }
25 int main()
26 {
27     int cases=1;
28     while(scanf("%d%d%d", &v, &e, &t) == 3 && v){
29         mem(G); mem(vis);
30         int uu,vv;
31         rep(i,e){
32             scanf("%d%d", &uu, &vv);
33             G[uu][vv] = G[vv][uu] = 1;
34         }
35         ans=0;
36         for(int i=1;i<=v;i++){
37             for(int j=1;j<=v;j++){
38                 if(G[i][j]){
39                     ans++;
40                     mem(degree);///补全有两种方案,第一种度数全部补成偶数,第二种保留两个奇点
41                     dfs(i);
42                     int p1=0;
43                     for(int i=1;i<=v;i++){
44                         if(degree[i]%2==1) p1++;
45                         //printf("%d ",degree[i]);
46                     }
47                     //printf("
");
48                     if(p1>=2) p1-=2;
49                     ans+=p1/2;
50                     //printf("%d
",p1);
51                 }
52             }
53         }
54         if(ans) ans--;//连接连通快的边等于连通快数减一
55         printf("Case %d: %d
",cases++,ans*t);
56     }
57     return 0;
58 }
原文地址:https://www.cnblogs.com/tooyoungtoosimple/p/4442913.html