欧拉回路+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 }