CF 21D Traveling Graph
来源:互联网 发布:校园安全事件网络诈骗 编辑:程序博客网 时间:2024/05/21 10:55
CF 21D Traveling Graph
题目大意:一张无向图有n个点(
题解:
如果这张图是一张欧拉图的话,那么存在一条欧拉回路通过所有的边一次,一定是最小的回路。如果不是欧拉图的话,那么可以通过补一些边使得它成为一张欧拉图。首先floyd处理出两点之间的最短距离,然后在奇数度顶点之间加边,将所有的顶点补为偶数度。实际上是求所有的奇数度顶点的一个最小权完美匹配,可以枚举二分图费用流解。那么最终的解就是所有边权和加上最小的费用流费用。
#include <bits/stdc++.h>using namespace std;const int MAXN = 25;const int MAXE = 10000;const int INF = 0x3f3f3f3f;class MCMF{public:struct Edge { int u,v,f,cost,next; Edge() {}; Edge(int u,int v,int f,int cost,int next):u(u),v(v),f(f),cost(cost),next(next) {};};Edge edge[MAXE];int n,k,head[MAXN],dis[MAXN],pe[MAXN],nEdge;bool vis[MAXN];void init() { memset(head,-1,sizeof(head)); nEdge=0;}void addedge(int u,int v,int c,int cost) { edge[nEdge]=Edge(u,v,c,cost,head[u]); head[u]=nEdge++; edge[nEdge]=Edge(v,u,0,-cost,head[v]); head[v]=nEdge++;}bool spfa(int src,int sink) { memset(vis,false,sizeof(vis)); memset(dis,0x3f3f3f3f,sizeof(dis)); memset(pe,-1,sizeof(pe)); queue<int> q; q.push(src); dis[src]=0; vis[src]=true; while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=false; for(int i=head[u];i!=-1;i=edge[i].next) { int f=edge[i].f,v=edge[i].v,cost=edge[i].cost; if(f&&dis[u]+cost<dis[v]) { dis[v]=dis[u]+cost; pe[v]=i; if(!vis[v]) { vis[v]=true; q.push(v); } } } } return dis[sink]<INF;}int min_cost_max_flow(int src,int sink) { int ans=0; while(spfa(src,sink)) { int delta=INF; for(int i=pe[sink];i!=-1;i=pe[edge[i].u]) delta=min(delta,edge[i].f); for(int i=pe[sink];i!=-1;i=pe[edge[i].u]){ edge[i].f-=delta; edge[i^1].f+=delta; }ans+=dis[sink]*delta; } return ans;}}mcmf;struct node{ int v,val; int next; node(int v,int val,int next):v(v),val(val),next(next){} node(){}}edge[MAXE];int head[MAXN],deg[MAXN],vis[MAXE],nn;void dfs(int u){ for(int i = head[u];~i;i= edge[i].next){ int v = edge[i].v; if(vis[i]||vis[i^1]) continue; vis[i] = 1; vis[i^1] = 1; dfs(v); }}void addedge(int u,int v,int w){ edge[nn] = node(v,w,head[u]); head[u] = nn++;}int dis[MAXN][MAXN];vector<int> V;void init(){ nn = 0; memset(head,-1,sizeof(head)); memset(deg,0,sizeof(deg)); memset(vis,0,sizeof(vis)); memset(dis,0x3f,sizeof(dis));}int main(){ int n,m,u,v,w; while(~scanf("%d%d",&n,&m)){ init(); V.clear(); int ans = 0; for(int i = 0;i < m;i++){ scanf("%d%d%d",&u,&v,&w); dis[u][v] = min(dis[u][v],w); dis[v][u] = dis[u][v]; ans += w; addedge(u,v,w); addedge(v,u,w); deg[u]++; deg[v]++; } dfs(1); int flag = 0; for(int i = 1;i <= n;i++) if(deg[i]%2) V.push_back(i); for(int i = 0;i < nn;i++) if(!vis[i]){ flag = 1; break; } if(flag){ puts("-1"); continue; } for(int k = 1;k <= n;k++) for(int i = 1;i <= n;i++) for(int j = 1;j <= n;j++) dis[i][j] = min(dis[i][j],dis[i][k]+dis[k][j]); int kk = V.size(); int tmp = 0; if(kk){ tmp = INF; for(int i = 1;i < 1<<kk;i++){ int t,cnt = 0; t = i; while(t){ if(t&1) cnt++; t>>=1; } if(cnt == kk/2){ mcmf.init(); for(int j = 0;j < kk;j++){ if((i>>j)&1){ mcmf.addedge(0,j+1,1,0); for(int k = 0;k < kk;k++){ if(!((i>>k)&1)){ mcmf.addedge(j+1,k+1,1,dis[V[j]][V[k]]); } } } else{ mcmf.addedge(j+1,kk+1,1,0); } } tmp = min(tmp,mcmf.min_cost_max_flow(0,kk+1)); } } } printf("%d\n",ans+tmp); } return 0;}
0 0
- CF 21D Traveling Graph
- 【Codeforces】 21D Traveling Graph
- CodeForces 21 D Traveling Graph
- CodeForces 21D Traveling Graph 状压dp+欧拉回路
- Codeforces Alpha Round #21 (Codeforces format) D. Traveling Graph
- CodeForces 21 D.Traveling Graph(状压DP+Floyd)
- 状态压缩DP joboj1430 shortest path 和 codeforces Problem 21 D Traveling Graph
- CodeForces 21D - Traveling Graph 欧拉回路的性质+状态压缩DP
- Codeforces Alpha Round #21 D. Traveling Graph(欧拉路,floyed,dp,好题)
- cf#161-D-Cycle in Graph- dfs
- cf-Round #214 (Div. 2)-D-Dima and Trap Graph-dfs+二分
- Traveling
- Traveling
- E. Soldier and Traveling (CF 304 div2) 最大流
- CF Soldier and Traveling(最大流SAP)拆点法
- cf 304 Soldier and Traveling 网络流 + 记录流量情况
- cf 80 div1 B(graph)
- CF 404C - Restore Graph
- AE学习笔记之空间查询
- 我的万年历程序,Calendar.java
- cf 714 e Sonya and Problem Wihtout a Legend
- 用python来玩科学计算
- oracle解锁
- CF 21D Traveling Graph
- Java类与类之间的关系
- java 图片打包
- 模板特例化,偏特化
- 在Docker中运行DPDK
- 安徽大学大一高数第二章习题册答案
- Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) G
- swift初学者(简单值)
- 洛谷 改数