【CodeForces - 260D】Black and White Tree (思维构造,猜结论,细节,构造一棵树)
題干:
The board has got a painted tree graph, consisting of?n?nodes. Let us remind you that a non-directed graph is called a tree if it is connected and doesn't contain any cycles.
Each node of the graph is painted black or white in such a manner that there aren't two nodes of the same color, connected by an edge. Each edge contains its value written on it as a non-negative integer.
A bad boy Vasya came up to the board and wrote number?sv?near each node?v?— the sum of values of all edges that are incident to this node. Then Vasya removed the edges and their values from the board.
Your task is to restore the original tree by the node colors and numbers?sv.
Input
The first line of the input contains a single integer?n?(2?≤?n?≤?105) — the number of nodes in the tree. Next?n?lines contain pairs of space-separated integers?ci,?si(0?≤?ci?≤?1,?0?≤?si?≤?109), where?ci?stands for the color of the?i-th vertex (0 is for white, 1 is for black), and?si?represents the sum of values of the edges that are incident to the?i-th vertex of the tree that is painted on the board.
Output
Print the description of?n?-?1?edges of the tree graph. Each description is a group of three integers?vi,?ui,?wi?(1?≤?vi,?ui?≤?n,?vi?≠?ui,?0?≤?wi?≤?109), where?vi?and?ui— are the numbers of the nodes that are connected by the?i-th edge, and?wi?is its value. Note that the following condition must fulfill?cvi?≠?cui.
It is guaranteed that for any input data there exists at least one graph that meets these data. If there are multiple solutions, print any of them. You are allowed to print the edges in any order. As you print the numbers, separate them with spaces.
Examples
Input
3 1 3 1 2 0 5Output
3 1 3 3 2 2Input
6 1 0 0 3 1 8 0 2 0 3 0 0Output
2 3 3 5 3 3 4 3 2 1 6 0 2 1 0題目大意:
? ?給你n個點,然后是每個點的顏色(用0或1表示)和 與這個點相鄰的邊的權值,讓你恢復一棵樹(輸出格式為u,v,w(邊權))
解題報告:
? ?首先告訴你一定有解了,那么我們只需要構造出一組解就可以了。(因為說明黑色的點的權值之和 等于 白色的點的權值之和)構造的方法選擇貪心,每次選擇兩個最小的黑白點然后 把權值較小的全都連到權值較大的邊上,最后別忘了特判剩下的頂點全為0的情況。。。細節不少啊。
AC代碼:
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #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; vector<pair<int, int> > a,b;//1==黑 0==白 int main() {int n;//cout << (1,0) << endl;cin>>n;for(int i=1,col,w; i<=n; i++) {scanf("%d%d",&col,&w);if(col) a.pb(pm(w,i));else b.pb(pm(w,i));}sort(a.begin(),a.end());sort(b.begin(),b.end()); // for(int i = 0; i<a.size(); i++) printf("%d %d\n",a[i].fi,a[i].se);int cnt1=0,cnt2=0;int up1=a.size();int up2=b.size(); // int zero1=0,zero2=0; // while(a[zero1].fi == 0) zero1++; // while(b[zero2].fi == 0) zero2++;while(cnt1 < up1 && cnt2 < up2) {int tmp = min(a[cnt1].fi,b[cnt2].fi);printf("%d %d %d\n",a[cnt1].se,b[cnt2].se,tmp);a[cnt1].fi -= tmp;b[cnt2].fi -= tmp; // if(a[cnt1].fi) cnt2++; // else if(b[cnt2].fi) cnt1++;if(a[cnt1].fi == 0 && cnt1 < up1-1) cnt1++;else if(b[cnt2].fi == 0 && cnt2 < up2-1) cnt2++;else if(cnt1 < up1-1) cnt1++;else cnt2++;}return 0 ;}?或者用上面那兩行注釋的也可以。
這樣寫是不對的:
while(cnt1 < up1 && cnt2 < up2) {int tmp = min(a[cnt1].fi,b[cnt2].fi);printf("%d %d %d\n",a[cnt1].se,b[cnt2].se,tmp);a[cnt1].fi -= tmp;b[cnt2].fi -= tmp; // if(a[cnt1].fi) cnt2++; // else if(b[cnt2].fi) cnt1++;if(a[cnt1].fi == 0 && cnt1 < up1) cnt1++;else if(b[cnt2].fi == 0 && cnt2 < up2) cnt2++;對于這樣的樣例
6 0 0 1 0 0 0 1 0 0 0 1 0是過不了的、、所以必須cnt1<up1-1這樣,對于其他的情況再另行判斷?
總結:
? 好cai啊、、、5555又被虐了
?其實為了避免上面那些 繁瑣的情況,還可以用優先隊列寫,最后清空的時候直接暴力清空就可以了。
總結
以上是生活随笔為你收集整理的【CodeForces - 260D】Black and White Tree (思维构造,猜结论,细节,构造一棵树)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 人民币连续7个月升值,创两年多新高,我们
- 下一篇: 【AtCoder - 4244 】AtC