日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

JZOJ 5939. 【NOIP2018模拟10.30】阻击计划

發布時間:2025/3/15 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JZOJ 5939. 【NOIP2018模拟10.30】阻击计划 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Description

最近,小J發現小R和小Z之間的關系十分密切,心中十分嫉妒,為了拆散他們,小J經常擾亂他們一起玩耍的計劃。
問題描述
小R和小Z打算在這個周末一起騎車在G國的城市看風景,G國的城市有n個城市,m條雙向道路,這m條邊中,有n-1條道路已經鋪設完畢,任意兩個城市之間都有一條由鋪設好的道路組成的路徑。
由于G國經常收到周圍強大力場的影響,G國的每個城市至多是十條道路的端點(包括鋪設好和未鋪設好的道路)。
小R和小Z制訂了這樣一個Van耍計劃:從一個城市開始,沿著G國的道路騎行,途中不經過之前已經去過的城市,也不經過之前去過的道路,最后回到起點城市。
由于他們騎得是雙人自行車,前排的座位比后排的作為更累,他們決定每次到達一個城市都會換一次位置,為了保證每個人的體力消耗相同,繼續進行他們下面的游戲,他們需要一條恰好有偶數條道路的路徑。
為了阻止他們,小J決定破壞一些沒有被鋪設好的道路,由于自身能力不足,他找到了你,并將自己一周的研究數據——破壞每條未被鋪設好的道路的花費告訴了你,希望你幫他算出他至少需要花費多少代價才能阻止小R和小Z的計劃。

Input

第一行兩個正整數n,m表示G國的城市數和道路數
接下來m行,每行三個整數A,B,C,表示G國的一條道路,從A出發到B,破壞它的代價為C(未經鋪設的道路C值一定不為0),由于小J智商有限,已經鋪設好的道路他不能毀壞,也就失去了偵察的必要,他們的花費為0

Output

一行一個整數表示小J的最小花費

Sample Input

Sample Input1:

5 8
2 1 0
3 2 0
4 3 0
5 4 0
1 3 2
3 5 2
2 4 5
2 5 1

Sample Input2:

9 14
1 2 0
1 3 0
2 3 14
2 6 15
3 4 0
3 5 0
3 6 12
3 7 13
4 6 10
5 6 0
5 7 0
5 8 0
6 9 11
8 9 0

Sample Output

Sample Output1:

5

樣例說明
破壞道路1-3,3-5,2-5

Sample Output2:

48

Data Constraint

對于5%的數據,任何一條未經鋪設的道路兩端都有一條直接連著他們的鋪設好的道路
對于另外10%的數據,最多只有10條未被鋪設的道路
對于另外15%的數據,最多只有21條未被鋪設的道路
對于上述兩檔部分分,數據有梯度
對于另外30%的數據,已經鋪設好的道路構成一條鏈
對于所有數據 n≤1000,m≤5000,每條道路的花費≤10000

Solution

  • 如果連接的新邊使圖構成一個偶環的話肯定就不行了,也就是連接兩點的樹上路徑長度不能為奇數。

  • 而且就算加進來是一個奇環,兩個奇環相交后也能形成一個偶環,這也不行。

  • 轉化一下,也就是說我們需要加最大權值的邊使原樹變成一顆仙人掌。

  • 看到一個點的度數不超過 101010 ,我們考慮 DP 。

  • f[i][S]f[i][S]f[i][S] 表示以 iii 為根的子樹且不考慮其一些兒子(其集合為 SSS)的最大權值。

  • 為了順暢轉移,我們將形成奇環(即可能行的)的新邊掛在其兩端點 x,yx,yx,y 的 Lca 處。

  • 我們 dfs 到一個點時就先處理完其子樹的 fff ,之后就能將掛在該點上的新邊拿出來更新答案。

  • 先賦初值:f[x][i]=∑j?if[j][0]f[x][i]=\sum_{j?i}f[j][0]f[x][i]=j/?i?f[j][0]

  • 對于一對 x,yx,yx,y(其 Lca 為 zzz) ,轉移將會是:f[x][i]=max{f[x][i∣2x′∣2y′]+sum}f[x][i]=max\{f[x][i\ |\ 2^{x'}\ |\ 2^{y'}]+sum\}f[x][i]=max{f[x][i??2x??2y]+sum}

  • 這里的 x′,y′x',y'x,y 分別是 x,yx,yx,yzzz 路徑上最接近 zzz 的點(即 zzz 的兩個兒子節點)。

  • 而選了 x,yx,yx,y 后其到 zzz 的路徑上就不能再選新邊了,于是我們統計一個 sumsumsum 記錄產生的轉移值。

  • 首先有 sum+=Csum+=Csum+=C (即該路徑的權值)。

  • 接著又有:sum+=f[x][0]+f[y][0]sum+=f[x][0]+f[y][0]sum+=f[x][0]+f[y][0]x,yx,yx,y 下面都能選)

  • 然后 x,yx,yx,yzzz 路徑上側鏈點的值也要統計上,大概:sum+=f[fa[p]][fa[p]除p外其他兒子]sum+=f[fa[p]][fa[p]除p外其他兒子]sum+=f[fa[p]][fa[p]p]

  • 統計時要特判 x=zx=zx=zy=zy=zy=z 的情況。

  • 時間復雜度 O(nm+210?n)O(nm+2^{10}*n)O(nm+210?n) 。

  • 由于數據的一些問題,有某些點的度數竟達到了12,故以下程序中開到了 2122^{12}212

Code

#include<cstdio> #include<algorithm> #include<cmath> #include<vector> #include<cctype> using namespace std; const int N=1005,M=1<<12; struct data {int x,y,z; }a[N<<2]; int tot,num,ans; int first[N],nex[N<<1],en[N<<1]; int dep[N],fa[N][10],p[13]; int f[N][M],val[N],bel[13]; vector<int>ss[N]; inline int read() {int X=0,w=0; char ch=0;while(!isdigit(ch)) w|=ch=='-',ch=getchar();while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();return w?-X:X; } inline void insert(int x,int y) {nex[++tot]=first[x];first[x]=tot;en[tot]=y; } inline int max(int x,int y) {return x>y?x:y; } void dfs(int x) {dep[x]=dep[fa[x][0]]+1;for(int i=first[x];i;i=nex[i])if(en[i]^fa[x][0]){fa[en[i]][0]=x;dfs(en[i]);} } inline int lca(int x,int y) {if(dep[x]<dep[y]) swap(x,y);for(int i=log2(dep[x]);i>=0;i--)if(dep[fa[x][i]]>=dep[y]) x=fa[x][i];if(x==y) return x;for(int i=log2(dep[x]);i>=0;i--)if(fa[x][i]^fa[y][i]) x=fa[x][i],y=fa[y][i];return fa[x][0]; } void dfs1(int x) {for(int i=first[x];i;i=nex[i])if(en[i]^fa[x][0]) dfs1(en[i]);tot=0;for(int i=first[x];i;i=nex[i])if(en[i]^fa[x][0]){bel[tot]=en[i];val[en[i]]=p[tot++];}for(int i=0;i<p[tot];i++){int sum=0;for(int j=0;j<tot;j++)if(!(i&p[j])) sum+=f[bel[j]][0];f[x][i]=sum;}for(int i=0;i<(int)ss[x].size();i++){int id=ss[x][i],px=0,py=0;int xx=a[id].x,yy=a[id].y,sum=a[id].z;if(xx^x){sum+=f[xx][0];for(px=xx;fa[px][0]^x;px=fa[px][0]) sum+=f[fa[px][0]][val[px]];}if(yy^x){sum+=f[yy][0];for(py=yy;fa[py][0]^x;py=fa[py][0]) sum+=f[fa[py][0]][val[py]];}for(int j=0;j<p[tot];j++)if(!(j&val[px]) && !(j&val[py]))f[x][j]=max(f[x][j],f[x][j|val[px]|val[py]]+sum);} } int main() {freopen("zujijihua.in","r",stdin);freopen("zujijihua.out","w",stdout);int n=read(),m=read();for(int i=1;i<=m;i++){int x=read(),y=read(),z=read();if(!z){insert(x,y);insert(y,x);}else{a[++num]=(data){x,y,z};ans+=z;}}dfs(1);for(int i=p[0]=1;i<13;i++) p[i]=p[i-1]<<1;for(int j=1;j<10;j++)for(int i=1;i<=n;i++)fa[i][j]=fa[fa[i][j-1]][j-1];for(int i=1;i<=num;i++){int x=a[i].x,y=a[i].y,z=lca(x,y);if((dep[x]+dep[y]-dep[z]*2)%2==0) ss[z].push_back(i);}dfs1(1);printf("%d",ans-f[1][0]);return 0; }

總結

以上是生活随笔為你收集整理的JZOJ 5939. 【NOIP2018模拟10.30】阻击计划的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。