Atcoder ARC063E Integers on a tree

题目链接

方法一:

  主要思想是从两个已经有值了的顶点向中间扩散,因为要使最后扩散完后两端最后扩散到的两个数差为1,所以可以考虑成要使扩散完后两端最后扩散到的两个数的差最小且不为0,于是可以使用贪心算法,每次取一个值最小的顶点开始扩散。如果最后扩散出的有2个相邻的顶点的值得差不为1,则为非法情况。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3  
 4 typedef long long ll;
 5 typedef unsigned long long ull;
 6 typedef pair<int, int> i_i;
 7 typedef pair<ll, int> ll_i;
 8 typedef pair<double, int> d_i;
 9 typedef pair<ll, ll> ll_ll;
10 typedef pair<double, double> d_d;
11 struct edge { int v, w; };
12  
13 #define rep(i, N) for (int i = 0; i < N; i++)
14 #define pb push_back
15  
16 ll MOD = 1000000007;
17 ll _MOD = 1000000009;
18 ll e10 = 1e10 + 10;
19 double EPS = 1e-10;
20  
21 int main() {
22     int N; cin >> N;
23     vector<vector<int> > G(N);
24     rep(i, N - 1) {
25         int a, b; scanf("%d%d", &a, &b);
26         a--; b--;
27         G[a].pb(b);
28         G[b].pb(a);
29     }
30     vector<int> d(N, -1);
31     priority_queue<i_i, vector<i_i>, greater<i_i> > pq;
32     int K; cin >> K;
33     while (K--) {
34         int v, p; scanf("%d%d", &v, &p);
35         v--;
36         d[v] = p;
37         pq.push(i_i(p, v));
38     }
39     while (!pq.empty()) {
40         i_i p = pq.top(); pq.pop();
41         int u = p.second;
42         cout<<u<<" "<<d[u]<<endl;
43         for (int v,i=0;i<G[u].size();i++){
44             v=G[u][i];
45             if (d[v] == -1) {
46                 d[v] = d[u] + 1;
47                 pq.push(i_i(d[v], v));
48             }
49         }
50     }
51     rep(u, N)
52         for (int i=0;i<G[u].size();i++){
53             int v=G[u][i];
54             if (abs(d[u] - d[v]) != 1) {
55                 cout << "No" << endl;
56                 return 0;
57             }
58         }
59     cout << "Yes" << endl;
60     rep(u, N) printf("%d\n", d[u]);
61 }

方法二:

  用树形dpdp出每个顶点可以取的数的上限和下限,如果满足奇偶性要求并且上限不大于下限则必有一组合法解。

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3  
  4 const int INF = 1e9;
  5 const int N = 110000;
  6  
  7 int n;
  8 vector<int> g[N];
  9 int known[N], val[N];
 10 int K;
 11 int l[N], r[N];
 12 int used[N];
 13 int known_parity[N][2];
 14 int shit;
 15  
 16 vector<int> order;
 17 int par[N];
 18  
 19 void dfs(int v)
 20 {
 21     used[v] = 1;
 22  
 23     l[v] = -1e9;
 24     r[v] = 1e9;
 25     for (int i = 0; i < g[v].size(); i++)
 26     {
 27         int to = g[v][i];
 28         if (used[to])
 29             continue;
 30         dfs(to);
 31         par[to] = v;
 32         if (known_parity[to][0])
 33             known_parity[v][1] = 1;
 34         if (known_parity[to][1])
 35             known_parity[v][0] = 1;
 36         l[v] = max(l[v], l[to] - 1);
 37         r[v] = min(r[v], r[to] + 1);
 38     }
 39     
 40     if (known[v] == 1)
 41     {
 42         l[v] = max(l[v], val[v]);
 43         r[v] = min(r[v], val[v]);
 44         known_parity[v][val[v] % 2] = 1;
 45     }
 46  
 47     if (known_parity[v][0] == 1 && known_parity[v][1] == 1)
 48     {
 49         shit = 1;
 50     }
 51  
 52     if (l[v] > r[v])
 53         shit = 1;
 54  
 55     order.push_back(v);
 56 }
 57  
 58 int ans[N];
 59  
 60 int solve_val(int v, int par)
 61 {
 62     if (par == 0)
 63     {
 64         return l[v];
 65     }
 66     l[v] = max(l[v], ans[par] - 1);
 67     r[v] = min(r[v], ans[par] + 1);
 68     while (l[v] % 2 == ans[par] % 2)
 69         ++l[v];
 70     return l[v];
 71 }
 72  
 73 int main(){
 74     //freopen("fabro.in","r",stdin);
 75     //freopen("fabro.out","w",stdout);
 76     //freopen("F:/in.txt", "r", stdin);
 77     //freopen("F:/output.txt", "w", stdout);
 78     ios_base::sync_with_stdio(0);
 79     //cin.tie(0);
 80     
 81     cin >> n;
 82     for (int i = 1; i < n; i++)
 83     {
 84         int a, b;
 85         cin >> a >> b;
 86         g[a].push_back(b);
 87         g[b].push_back(a);
 88     }
 89  
 90     cin >> K;
 91     for (int i = 1; i <= K; i++)
 92     {
 93         int a, b;
 94         cin >> a >> b;
 95         known[a] = 1;
 96         val[a] = b;
 97     }
 98  
 99     dfs(1);
100  
101     if (shit)
102     {
103         cout << "No" << endl;
104         return 0;
105     }
106  
107     reverse(order.begin(), order.end());
108  
109     cout << "Yes" << endl;
110  
111     for (int i = 0; i < order.size(); i++)
112     {
113         int v = order[i];
114         if (par[v] == 0)
115         {
116             ans[v] = solve_val(v,par[v]);
117         }
118         else
119         {
120             ans[v] = solve_val(v, par[v]);
121         }
122     }
123  
124     for (int i = 1; i <= n; i++)
125     {
126         cout << ans[i] << endl;
127     }
128  
129     cin.get(); cin.get();
130     return 0;
131 }

方法三:

  主要思想是设uv的子树中的一个点,任意u都满足dep[u]-dep[v]>=ans[u]-ans[v]&&dep[u]>=ans[v]-ans[u]是子树合法的充分必要条件,可以变形为dep[u]-ans[u]>=dep[v]-ans[v]&&dep[u]+ans[u]>=dep[v]-ans[v],于是可以建线段树,线段树中的每一个叶子结点的下标表示ans[v]的一个值,叶子结点的值表示dep[u]-ans[u]dep[u]+ans[u],每一个节点的值表示[l,r]dep[u]-ans[u]的最小值和dep[u]+ans[u]的最小值,构造的时候可以直接查询当前填上的ans[v]是否满足dep[u]-ans[u]>=dep[v]-ans[v]dep[u]+ans[u]>=dep[v]-ans[v]。这里要用到线段树合并。

  1 #include<bits/stdc++.h>
  2 #define per(i,j,k) for(int i=(int)j;i>=(int)k;i--)
  3 #define rep(i,j,k) for(int i=(int)j;i<=(int)k;i++)
  4 using namespace std;
  5 const int N=110000;
  6 int head[N],np[N<<1],p[N<<1],tot;
  7 int key[N];
  8 int n,K;
  9 int root;
 10 int fa[N];
 11 int dep[N];
 12 int dx[2]={-1,1};
 13 int seg[N],cl[N*35],cr[N*35],segtot,mi[N*35][2];
 14 void copy(int x,int y){
 15     if(!y){
 16         rep(i,0,1)mi[x][i]=(1e9);
 17     }
 18     else{
 19         cl[x]=cl[y];
 20         cr[x]=cr[y];
 21         rep(i,0,1)mi[x][i]=mi[y][i];
 22     }
 23 }
 24 void insert(int &me,int l,int r,int x,int v){
 25     ++segtot;
 26     copy(segtot,me);
 27     me=segtot;
 28     if(l==r){
 29         rep(i,0,1)mi[me][i]=v+dx[i]*x;
 30         return;
 31     }
 32     int mid=(l+r)>>1;
 33     if(x<=mid)insert(cl[me],l,mid,x,v);
 34     else insert(cr[me],mid+1,r,x,v);
 35  
 36     rep(i,0,1)mi[me][i]=min(mi[cl[me]][i],mi[cr[me]][i]);
 37 }
 38 int merge(int a,int b,int l,int r){
 39     if(!a||!b)return a+b;
 40     int d=++segtot;
 41  
 42     if(l==r){
 43         rep(i,0,1)mi[d][i]=min(mi[a][i],mi[b][i]);
 44         return d;
 45     }
 46     int mid=(l+r)>>1;
 47     cl[d]=merge(cl[a],cl[b],l,mid);
 48     cr[d]=merge(cr[a],cr[b],mid+1,r);
 49     rep(i,0,1)mi[d][i]=min(mi[cl[d]][i],mi[cr[d]][i]);
 50     return d;
 51 }
 52 void dfs(int x){
 53     for(int u=head[x];u;u=np[u])if(p[u]^fa[x]){
 54         fa[p[u]]=x;dep[p[u]]=dep[x]+1;dfs(p[u]);
 55         seg[x]=merge(seg[x],seg[p[u]],0,100000);
 56     }
 57     if(key[x]>=0){
 58         insert(seg[x],0,100000,key[x],dep[x]);
 59     }
 60 }
 61 int ask(int k,int me,int l,int r,int x,int y){
 62     if((x>y)||(!me))return 1000000000;
 63     if(x<=l&&r<=y)return mi[me][k];
 64     int ret=1000000000;
 65     int mid=(l+r)>>1;
 66     if(x<=mid){
 67         int D=ask(k,cl[me],l,mid,x,y);
 68         if(D<ret)ret=D;
 69     }
 70     if(y>mid){
 71         int D=ask(k,cr[me],mid+1,r,x,y);
 72         if(D<ret)ret=D;
 73     }
 74     return ret;
 75 }
 76 void work(int x,int fav){
 77     //printf("%d %d\n",x,fav);
 78     if(key[x]>=0){
 79         fav=key[x];
 80         for(int u=head[x];u;u=np[u])if(p[u]^fa[x])work(p[u],fav);
 81         return;
 82     }
 83     //1
 84     bool flag=1;
 85     fav++;
 86     int dj=ask(1,seg[x],0,100000,0,fav);
 87     if(dj<dep[x]+fav)flag=0;                      //dep[v]+val[v]>=dep[now]+val[now]-->dep[v]-dep[now]>=val[now]-val[v]
 88     //printf("__+ %d\n",dj);
 89     dj=ask(0,seg[x],0,100000,fav,100000);         //dep[v]-val[v]>=dep[now]-val[now]-->dep[v]-dep[now]>=val[v]-val[now]
 90     //printf("__+ %d\n",dj);
 91     if(dj<dep[x]-fav)flag=0;
 92     if(flag){
 93         key[x]=fav;
 94         for(int u=head[x];u;u=np[u])if(p[u]^fa[x])work(p[u],fav);
 95         return;
 96     }
 97     //-1
 98     fav-=2;
 99     flag=1;
100     dj=ask(1,seg[x],0,100000,0,fav);
101     if(dj<dep[x]+fav)flag=0;
102     dj=ask(0,seg[x],0,100000,fav,100000);
103     if(dj<dep[x]-fav)flag=0;
104     if(flag){
105         key[x]=fav;
106         for(int u=head[x];u;u=np[u])if(p[u]^fa[x])work(p[u],fav);
107         return;
108     }
109 }
110 int main(){
111     rep(i,0,1)mi[0][i]=1e9;
112     scanf("%d",&n);
113     rep(i,1,n-1){
114         int a,b;scanf("%d%d",&a,&b);
115         ++tot;p[tot]=b;np[tot]=head[a];head[a]=tot;
116         ++tot;p[tot]=a;np[tot]=head[b];head[b]=tot;
117     }
118     scanf("%d",&K);
119     rep(i,1,n)key[i]=-10000000;
120     rep(i,1,K){
121         int v,p;scanf("%d%d",&v,&p);
122         key[v]=p;
123         root=v;
124     }
125     dfs(root);
126     work(root,10086);
127     rep(i,1,n)if(i!=root)if(abs(key[i]-key[fa[i]])!=1){
128         printf("No\n");
129         return 0;
130     }
131     printf("Yes\n");
132     rep(i,1,n)printf("%d\n",key[i]);
133     return 0;
134 }

猜你喜欢

转载自www.cnblogs.com/unnamed05/p/9824659.html