CodeForces - 1339D Edge Weight Assignment(思维)
題目鏈接:點擊查看
題目大意:給出一棵樹,初始時每條邊都沒有權值,要求給 n - 1 條邊賦值,需要滿足任意兩個葉子結點之間路徑上的權值異或和為 0 ,設邊權的種類為 k ,求 k 的最小值和最大值
題目分析:一開始以為是一個構造題,然后又想偏了,其實題目已經給提示了,那就是說邊權的值可能會很大很大,這就提示我們說,如果滿足某種條件的話,那么肯定是可以找出一種賦值對應答案的,這個題最終也只需要輸出邊權種類的兩個最值,而不需要輸出具體的賦值情況
回到這個題目上來,其實最小值不難想,什么情況可以使得所有的邊權都使用同一個數呢?根據兩個相同的數異或等于 0 這個小結論,不難得出只有任意兩個葉子結點之間簡單路徑上邊的個數為偶數時才是可行的,換句話說,跑一下樹的深度,所有葉子結點的奇偶性如果相同,那就說明滿足條件,最小值就是 1 ,否則就是 3 ,這里的 3 又該如何理解呢,既然存在兩個葉子結點之間的簡單路徑是奇數條,可以拿出三條邊,賦值使其異或和為 0 ,剩下的邊肯定是偶數條了,再用上面的方法處理就好了,這樣最小值非一即三,跑一次dfs得到數的深度就能判斷了
關于最大值,猜結論的話答案就是:初始時 ans = n - 1 ,對于每個節點而言,與其相連的葉子結點設有 cnt 個,則對答案的貢獻為 ans -= max( 0 , cnt - 1 )?
為什么可以這樣想呢?因為如果想讓異或和為 0 的話,只有兩個數的話,當且僅當這兩個數相同時異或和才為 0 ,但是如果是三個及以上的數的話,就總是存在著一種賦值使得這些數都不相同且異或和為零,所以我們只需要找出有多少對葉子結點之間的距離小于等于 2 ,那就說明這些葉子結點的賦值必須一樣才能滿足異或和為 0 ,而其余沒有涉及到的邊肯定是可以找到一種賦值滿足邊權皆不相同且異或和為 0 這個條件的
代碼:
#include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<unordered_map> using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=1e5+100;vector<int>node[N];bool flag;int deep[N];void dfs(int u,int fa,int dep) {deep[u]=dep;if(node[u].size()==1&&(deep[u]&1))flag=true;for(auto v:node[u]){if(v==fa)continue;dfs(v,u,dep+1);} }int main() { #ifndef ONLINE_JUDGE // freopen("input.txt","r",stdin); // freopen("output.txt","w",stdout); #endif // ios::sync_with_stdio(false);int n;scanf("%d",&n);for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);node[u].push_back(v);node[v].push_back(u);}int root;for(int i=1;i<=n;i++)if(node[i].size()==1){root=i;break;}flag=false;dfs(root,-1,0);int mmin=flag?3:1;int mmax=n-1;for(int u=1;u<=n;u++){int cnt=0;for(auto v:node[u])if(node[v].size()==1)cnt++;mmax-=max(0,cnt-1);}printf("%d %d\n",mmin,mmax);return 0; }?
總結
以上是生活随笔為你收集整理的CodeForces - 1339D Edge Weight Assignment(思维)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CodeForces - 1339C P
- 下一篇: CodeForces - 1339E P