「模拟8.21」虎

正解贪心考场只骗到了70分

做法一:

现将没有限制的边缩掉然后连边,

这样我们直接采用贪心的做法,因为每个边最多只会被反一次,

那么从叶子节点向上对于一个需要修改的边没直接令他向上直到不能修改

注意处理连在lca上有两条链的现象

 1 #include<bits/stdc++.h>
 2 #define MAXN 2100000
 3 using namespace std;
 4 struct node{int to;int n;}e[MAXN];
 5 int tot,head[MAXN];
 6 int n;bool ok_1;int work_1;
 7 int fa[MAXN];int col[MAXN];
 8 bool h[MAXN];
 9 vector<int>son[MAXN];
10 void add(int u,int v)
11 {
12      e[++tot].to=v;e[tot].n=head[u];head[u]=tot;
13 }
14 void work1()
15 {
16      if(work_1%2==0)printf("%d\n",work_1/2);
17      else printf("%d\n",work_1/2+1);
18 }
19 int ans=0;
20 int biao[MAXN];
21 void updata(int x)
22 {
23      int me=x;
24      while(col[me]==0&&me!=1)
25      {
26            col[me]^=1;
27            me=fa[me];
28      }        
29      biao[me]^=1;
30      if(biao[me]==1)
31      {
32         ans++;        
33      }
34      return ;
35 }
36 void DFS(int x)
37 {
38      for(int i=head[x];i;i=e[i].n)
39      {
40          int to=e[i].to;
41          DFS(to);
42          if(col[to]==0)
43          {
44             updata(to);
45          }
46      }
47      return ;
48 }
49 signed main()
50 {
51      scanf("%d",&n);ok_1=1;
52      for(int i=2;i<=n;++i)
53      {
54          int x,y,z;
55          scanf("%d%d%d",&x,&y,&z);
56          if(x!=1)ok_1=0;
57          if(z==1&&y==0)work_1++;
58          if(z==0)h[i]=1;
59          fa[i]=x;col[i]=y;
60          son[x].push_back(i);
61      }
62      for(int i=2;i<=n;++i)
63      {
64          int me=i;
65          if(h[i]==1)
66          {
67              while(h[me]==1&&me!=1)
68                    me=fa[me];
69              for(int j=0;j<son[i].size();++j)
70              {
71                  fa[son[i][j]]=me;
72              }
73          }
74      }
75      for(int i=2;i<=n;++i)
76      {
77          if(h[i])continue;
78          add(fa[i],i);
79      }
80      if(ok_1)
81      {
82         work1();
83         return 0;
84      }
85      DFS(1);
86      printf("%d\n",ans);
87 }
View Code

做法二

我们如果能在一个lca上连两条边,那么这一定是优的

那么我们从下向上统计奇数偶数边的情况

参考cyf的代码

 1 #include<cstdio>
 2 #include<iostream>
 3 #define INF 0x7fffffff
 4 using namespace std;
 5 const int MAXN=1000010;
 6 inline int minn(int a,int b){return a<b?a:b; }
 7 inline int read(){
 8     int s=0,w=0;char ch=getchar();
 9     while(ch<'0'||ch>'9')w|=(ch=='-'),ch=getchar();
10     while(ch>='0'&&ch<='9')s=s*10+ch-'0',ch=getchar();
11     return w?-s:s;
12 }
13 #define kd (read())
14 int n;
15 struct rr{
16     int nt,w,to;
17 }bl[MAXN<<1];int hd[MAXN],itot;
18 void add(int x,int y,int z){
19     if(x==y)return ;
20     bl[++itot].to=y;
21     bl[itot].nt=hd[x];
22     bl[itot].w=z;
23     hd[x]=itot;
24 }
25 int fat[MAXN];
26 inline int find(int x){
27     if(!fat[x]||fat[x]==x)return x;
28     return fat[x]=find(fat[x]);
29 }
30 struct node{
31     int fr,to,y;
32 }Q[MAXN];int qtot;
33 int ans=0;
34 void dfs(int u,int fa,int id){//id of edge fa->u  
35     int cnt=0;
36     for(int i=hd[u];i;i=bl[i].nt)
37         if(bl[i].to!=fa){
38             dfs(bl[i].to,u,i);
39             cnt+=(bl[i].w==0);
40         }
41     if(cnt&1){
42         ans+=cnt/2;
43         if(bl[id].w==1)++ans;
44     }
45     else ans+=cnt/2;
46 }
47 int main(){
48     //freopen("da.in","r",stdin);
49     n=kd;
50     bool pd_30=1;
51     int cnt=0;
52     for(int i=2,x,y,z;i<=n;++i){
53         x=kd;y=kd;z=kd;
54         pd_30&=(x==1);
55         if(z&&!y)++cnt;
56         if(!z)fat[find(i)]=find(x);
57         Q[++qtot].fr=i,Q[qtot].to=x,Q[qtot].y=y;
58     }
59     if(pd_30){
60         if(cnt&1)printf("%d\n",cnt/2+1);
61         else printf("%d\n",cnt/2);
62         return 0;
63     }
64     else{
65         for(int i=1;i<=qtot;++i){
66             add(find(Q[i].fr),find(Q[i].to),Q[i].y);
67             add(find(Q[i].to),find(Q[i].fr),Q[i].y);
68         }
69         bl[0].w=1;
70         dfs(find(1),0,0);
71         printf("%d\n",ans);
72         return 0;
73     }
74 }
View Code

猜你喜欢

转载自www.cnblogs.com/Wwb123/p/11420940.html