【学习笔记】BZOJ2887 旅行

在家学习总忍不住颓废

妙题。首先如果小地图存在欧拉回路,那么大地图上的 u → v u\to v uv v → u v\to u vu都走一遍就能恰好遍历完小地图上的所有边。

否则一定存在欧拉路。

如果经过这条边 1 1 1次,设欧拉路起点为 a a a, b b b,那么相当于在原图上多走一些边使得变成起点为 f ( u ) f(u) f(u),终点为 f ( v ) f(v) f(v)的图,并且这些多走的边相当于少掉的贡献,相当于将 a a a, b b b, f ( u ) f(u) f(u), f ( v ) f(v) f(v)分成两组使得最短路之和最小。

如果经过这条边 2 2 2次,那么相当于总的边权减去 a a a b b b的最短路。

然后我们求出大图的一个生成树,枚举不在生成树上的边的状态,那么树边的状态是唯一确定的。并且整个图是联通的,因此构造合法。

#include<bits/stdc++.h> #define fi first #define se second #define ll long long #define pb push_back using namespace std; int n,m,P,Q,p[10005],vis[10005],vis2[10005],in[205],du[10005]; ll a[205][205],sum; struct node{ int u,v; }e[20005]; vector<pair<int,int>>g[10005]; vector<int>vec; vector<pair<int,int>>vec2; vector<int>vv; void dfs(int u){ vis[u]=1; for(auto v:g[u]){ if(!vis[v.fi])vis2[v.se]=1,dfs(v.fi),vec2.pb({u,v.fi}); } } ll calc(int u,int v,int w){ u=p[u],v=p[v]; int U=vv[0],V=vv[1]; if(!w)return sum-a[U][V]; return sum-min({a[u][v]+a[U][V],a[u][U]+a[v][V],a[u][V]+a[v][U]}); } int main(){ ios::sync_with_stdio(false); cin.tie(0),cout.tie(0); cin>>n>>m>>P>>Q; for(int i=1;i<=n;i++)cin>>p[i]; for(int i=1;i<=m;i++){ int u,v;cin>>u>>v,g[u].pb({v,i}),g[v].pb({u,i}),e[i]={u,v}; }memset(a,0x3f,sizeof a); for(int i=1;i<=Q;i++){ int u,v,w;cin>>u>>v>>w,in[u]++,in[v]++,a[u][v]=a[v][u]=w,sum+=w; }for(int i=1;i<=P;i++)a[i][i]=0; for(int k=1;k<=P;k++){ for(int i=1;i<=P;i++){ for(int j=1;j<=P;j++){ a[i][j]=min(a[i][j],a[i][k]+a[k][j]); } } } dfs(1); for(int i=1;i<=P;i++){ if(in[i]&1)vv.pb(i); }if(!vv.size()){ cout<<sum*m; return 0; } for(int i=1;i<=m;i++){ if(!vis2[i])vec.pb(i); }int cnt=vec.size();ll tmp=0; assert(vv.size()==2); for(int i=0;i<1<<cnt;i++){ ll res=0; for(int j=0;j<cnt;j++){ int u=e[vec[j]].u,v=e[vec[j]].v; if(i>>j&1){ du[u]^=1,du[v]^=1; res+=calc(u,v,1); } else { res+=calc(u,v,0); } } for(int j=0;j<vec2.size();j++){ int u=vec2[j].fi,v=vec2[j].se; if(du[v])du[v]^=1,du[u]^=1,res+=calc(u,v,1); else res+=calc(u,v,0); } if(!du[1]){ tmp=max(tmp,res); } memset(du,0,sizeof du); }cout<<tmp; }

__EOF__

本文作者仰望星空的蚂蚁
本文链接https://www.cnblogs.com/cqbzly/p/17530078.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   仰望星空的蚂蚁  阅读(8)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
历史上的今天:
2021-12-10 关于自己犯过的错误
2021-12-10 【题解】[CQOI2017] 老C的方块
点击右上角即可分享
微信分享提示