在家学习总忍不住颓废
妙题。首先如果小地图存在欧拉回路,那么大地图上的
u
→
v
u\to v
u → v 和
v
→
u
v\to u
v → u 都走一遍就能恰好遍历完小地图上的所有边。
否则一定存在欧拉路。
如果经过这条边
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__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
2021-12-10 关于自己犯过的错误
2021-12-10 【题解】[CQOI2017] 老C的方块