【牛客 - 370F】Rinne Loves Edges(树,统计dp)
生活随笔
收集整理的這篇文章主要介紹了
【牛客 - 370F】Rinne Loves Edges(树,统计dp)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題干:
Rinne? 最近了解了如何快速維護可支持插入邊刪除邊的圖,并且高效的回答一下奇妙的詢問。
她現在拿到了一個 n 個節點 m 條邊的無向連通圖,每條邊有一個邊權 wiwi
現在她想玩一個游戲:選取一個 “重要點” S,然后選擇性刪除一些邊,使得原圖中所有除 S 之外度為 1 的點都不能到達 S。
定義刪除一條邊的代價為這條邊的邊權,現在 Rinne 想知道完成這個游戲的最小的代價,這樣她就能輕松到達 rk1 了!作為回報,她會讓你的排名上升一定的數量。
?
輸入描述:
第一行三個整數 N,M,S,意義如「題目描述」所述。接下來 M 行,每行三個整數 u,v,w 代表點 u 到點 v 之間有一條長度為 w 的無向邊。輸出描述:
一個整數表示答案。示例1
輸入
復制
4 3 1 1 2 1 1 3 1 1 4 1輸出
復制
3說明
需要使得點 2,3,4 不能到達點 1,顯然只能刪除所有的邊,答案為 3示例2
輸入
復制
4 3 1 1 2 3 2 3 1 3 4 2輸出
復制
1說明
需要使得點 4 不能到達點 1,顯然刪除邊?2?32?3是最優的。備注:
2≤S≤N≤105,M=N?12≤S≤N≤105,M=N?1,保證答案在 C++ long long 范圍內。解題報告:
? ?不算難的樹形dp,剛開始讀題錯了,所以代碼不太對、、
于是題目轉變求為了一棵根為 S 的樹,選擇性切掉一些邊,使得所有的葉子都不能到達根的最小代價。
讓我們考慮樹形dp(其實可能就是個統計算不上dp):設 fv 表示使得以 v 為根的子樹內的葉子到不了 v 的最小代價,轉移顯然枚舉每一條邊切不切就可以了。
方程大概是這樣:設當前我們要更新的點是 u,u 的一個兒子是 v,他們之間的邊的邊權是 w。則有轉移方程 fu+=min{fv,w}。
AC代碼:
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<ctime> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define ll long long #define pb push_back #define pm make_pair #define fi first #define se second using namespace std; const int MAX = 2e5 + 5; int t; int n,m,s,tot; int head[MAX]; int in[MAX]; struct Edge{int u,v,ne;ll w; } e[MAX]; void add(int u,int v,ll w) {e[++tot].u = u;e[tot].v = v;e[tot].w = w;e[tot].ne = head[u];head[u] = tot; } ll dfs(int cur,int root,ll val) {//ll res = 9223372036854775807;ll tmp = 0;for(int i = head[cur]; i!=-1; i=e[i].ne) {if(e[i].v == root) continue;//res = min(res,e[i].w);if(in[e[i].v] == 1) {tmp += e[i].w;continue;} // if(in[e[i].v] == 1) continue;tmp += dfs(e[i].v,cur,e[i].w);}return min(tmp,val); } int main() {cin>>n>>m>>s;memset(head,-1,sizeof head);int a,b;ll c;for(int i = 1; i<=m; i++) {scanf("%d%d%lld",&a,&b,&c);add(a,b,c);add(b,a,c);in[a]++,in[b]++;}ll ans = 0;for(int i = head[s]; i != -1; i = e[i].ne) {if(in[e[i].v] == 1) ans += e[i].w;else ans += dfs(e[i].v,s,e[i].w); } printf("%lld\n",ans);return 0 ; }錯誤代碼:
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<ctime> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define ll long long #define pb push_back #define pm make_pair #define fi first #define se second using namespace std; const int MAX = 2e5 + 5; int t; int n,m,s,tot; int head[MAX]; int in[MAX]; struct Edge{int u,v,ne;ll w; } e[MAX]; void add(int u,int v,ll w) {e[++tot].u = u;e[tot].v = v;e[tot].w = w;e[tot].ne = head[u];head[u] = tot; } ll dfs(int cur,int root) {ll res = 9223372036854775807;//int isye = 1;for(int i = head[cur]; i!=-1; i=e[i].ne) {if(e[i].v == root) continue;//isye = 0;res = min(res,e[i].w);if(in[e[i].v] == 1) {continue;}res = min(res,dfs(e[i].v,cur));}//if(isye == 1) returnreturn res; } int main() {cin>>n>>m>>s;memset(head,-1,sizeof head);int a,b;ll c;for(int i = 1; i<=m; i++) {scanf("%d%d%lld",&a,&b,&c);add(a,b,c);add(b,a,c);in[a]++,in[b]++;}ll ans = 0;for(int i = head[s]; i != -1; i = e[i].ne) {if(in[e[i].v] == 1) ans += e[i].w;else ans += dfs(e[i].v,s);}printf("%lld\n",ans);return 0 ; }AC代碼2:
#include<bits/stdc++.h> using namespace std; int n,m,s; struct edge {int to;int cost; }; vector<edge> e[110005]; bool vis[100005]; int mem[100005]; long long dp(int i,int pre) {if(e[i].size()==1&&i!=s){return e[i][0].cost;}if(mem[i]!=-1)return mem[i];vis[i]=1;long long res=0;int nxt;int co;edge tmp;for(int j=0;j<e[i].size();j++){tmp=e[i][j];nxt=tmp.to;if(vis[nxt])continue;co=tmp.cost;res+=dp(nxt,min(co,pre));}res=min(res,(long long)pre);mem[i]=res;return res; } int main() {//freopen("in.txt","r",stdin);memset(mem,-1,sizeof(mem));scanf("%d%d%d",&n,&m,&s);int u,v,w;edge tmp;for(int i=1;i<=m;i++){scanf("%d%d%d",&u,&v,&w);tmp.cost=w;tmp.to=v;e[u].push_back(tmp);tmp.to=u;e[v].push_back(tmp);}long long ans=dp(s,0x3f3f3f3f);cout<<ans<<endl;return 0; }官方標程:
#include <algorithm> #include <iostream> #include <cstring> #include <climits> #include <cstdio> #include <vector> #include <cstdlib> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <map> #include <set>#define Re register #define LL long long #define U unsigned #define FOR(i,a,b) for(Re int i = a;i <= b;++i) #define ROF(i,a,b) for(Re int i = a;i >= b;--i) #define SFOR(i,a,b,c) for(Re int i = a;i <= b;i+=c) #define SROF(i,a,b,c) for(Re int i = a;i >= b;i-=c) #define CLR(i,a) memset(i,a,sizeof(i)) #define BR printf("--------------------\n") #define DEBUG(x) std::cerr << #x << '=' << x << std::endlconst int MAXN = 100000+5;struct Edge{int to,w,next; }e[MAXN<<1]; int head[MAXN],cnt; LL f[MAXN];inline void add(int u,int v,int w){e[++cnt] = (Edge){v,w,head[u]};head[u] = cnt; }void dfs(int v,int fa=0){bool flag = true;for(int i = head[v];i;i = e[i].next){if(e[i].to == fa) continue;flag = false;dfs(e[i].to,v);f[v] += std::min(1ll*e[i].w,f[e[i].to]);}if(flag) f[v] = INT_MAX; }int N,root;int main(){scanf("%d%*d%d",&N,&root);FOR(i,1,N-1){int u,v,w;scanf("%d%d%d",&u,&v,&w);add(u,v,w);add(v,u,w);}dfs(root);printf("%lld\n",f[root]);return 0; }?
總結
以上是生活随笔為你收集整理的【牛客 - 370F】Rinne Loves Edges(树,统计dp)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: winmgm32.exe - winmg
- 下一篇: 女乘客在地铁内跳舞 成都地铁通报