「Luogu P3931」SAC E#1 - 一道難題 Tree 解題報告
阿新 • • 發佈:2018-12-18
圓原題面
我環顧四周,發現大佬們的寫法都好高階!
比較差勁的我,只能交上一份DFS的題解
思路:
DFS(當然了,其他演算法也行)
要想切斷葉子節點到根節點的連線
就是在葉子節點和根節點之間砍掉一條邊
這明顯就很符合DFS的性質,一條路一直走下去,遇到分枝就分開走
於是我們DFS每一條路徑,然後求答案
複雜度為O(n)
但是——還沒完!
我們可以發現DFS有三種情況
1、該節點為葉子節點,此時只能刪去連線它和父節點的邊
2、該節點為枝節點,有父節點和子節點,需要選擇性的刪除
3、該節點為根節點,只有子節點,只能刪去連線它和子節點的邊
Code:
#include<bits/stdc++.h> #define INF 0x7f7f7f7f using namespace std; struct node{ int to,cost; int nxt; node(int a,int b):to(a),cost(b){ } node(){ } }b[200010]; int n,t,r; int head[100010]; int read() { int s=0; char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) { s=(s<<1)+(s<<3)+c-'0'; c=getchar(); } return s; } void add(int x,int y,int cost)//建邊 { b[++t]=node(y,cost); b[t].nxt=head[x]; head[x]=t; b[++t]=node(x,cost); b[t].nxt=head[y]; head[y]=t; return; } int Get(int k,int in) { int i; int res=0; for(i=head[k];i;i=b[i].nxt) if(i!=(in^1))//成對變換原理,異或值相同但方向相反的邊為一組,避免重複 res+=Get(b[i].to,i); if(!b[head[k]].nxt&&k!=r)//確定是葉子節點 res=b[in].cost; else res=min(res,b[in].cost);//否則兩種方法選其一 return res; } int main() { int i; int x,y,cost; n=read();r=read(); t=1;//初始賦1,利於成對變換 for(i=1;i<n;i++) { x=read();y=read();cost=read(); add(x,y,cost); } b[0].cost=INF;//對於根節點的雙重保險,防止出什麼岔子,比如結果為0 printf("%d",Get(r,0)); return 0; }