zoukankan      html  css  js  c++  java
  • NOI ONLINE 提高组 序列 根据性质建图

    题目链接

      https://www.luogu.com.cn/problem/P6185

    题意

      应该不难懂,跳过

    分析

      说实话第一眼看到这题的时候我有点懵,真不知道怎么做,不过一看数据,还好还好,暴力能拿一半分,于是我就真拿了一半分。。。。。

      但某大佬说暴力能拿60,但我拿一半就满意了   我不会啊

      考完后忍不住好奇这道题要怎么做,于是就看了看题解,发现题解也。。。有点难懂,主要是我看到一个字,图??这明明是个数的问题咋还和图扯上了关系,awsl,果然还是我太       

         仔细读了一下,明白了一些。先看操作一:如果有(a1,a2)(a2,a3)(a3,a1),那么其中任意一个数都能自己加减二,如a1,a1+1,a2+1,a2-1,a3-1,a3+1,a1+1这样就能让a1自己加减二,同理a1换成任何数都可以,这里要注意,必须是奇数个点并且形成环才能这样办,所以每个奇数环上的数都能加减二,偶数个点为什么不行自己举个例子就明白了。再看操作二:如果有(a1,a2)(a2,a3)那么可以知道(a1,a3),a1+1,a2-1,a2+1,a3-1由此,a1+1,a3-1,可见操作二是具有传递性的,如果把它们看做是一个联通块,那么这个联通块可以任意加1,减1,所以如果这个联通块需要加的值和需要减的值一样,那么就满足。于是我们只要把每个操作二都缩成点,每个操作一建边,然后开始判断每块联通块是不是满足题意。

    判断方法为,如果未形成奇数环,则需要使联通块内相加的数与相减的数相等,因为只能加一减一,否则使需要变化的总数是偶数即可,注意自环也要判断,因为自环相当于(a1,a2,1)(a1,a2,2)即a1+1,a2+1,a2-1,a1+1,这样也能使任意数加减二,

    然后还有就是对于没有边连入的点,只有需要变化的值为0,才满足,因为没有边可以使它产生变化。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int N=2e5+10;
     6 long long val[N];
     7 struct Edge{
     8     int to,next;
     9 }e[N];
    10 struct Node{
    11     int t,u,v;
    12 }p[N];
    13 int Head[N],len,sum,flag;
    14 void Ins(int a,int b){
    15     e[++len].to=b;e[len].next=Head[a];Head[a]=len;
    16 }
    17 int f[N],belong[N],a[N],b[N];
    18 int find(int x){
    19     return f[x]==x?x:(f[x]=find(f[x]));
    20 }
    21 void Mer(int a,int b){
    22     int u=find(a),v=find(b);
    23     if(u!=v){
    24         f[u]=v;val[v]+=val[u];//并查集缩点
    25     }
    26 }
    27 void dfs(int x,int bin){
    28     belong[x]=bin;
    29     if(bin)sum+=val[x];
    30     else sum-=val[x];
    31     for(int i=Head[x];i;i=e[i].next){
    32         int v=e[i].to;
    33         if(belong[v]==-1)dfs(v,bin^1);//利用了^的性质
    34         else if(belong[x]==belong[v])//说明v已经被提前访问过并且bin的值与x一样,那么就一定形成了奇数环
    35             flag=1;
    36     }
    37 }
    38 int main(){
    39 //    freopen("a.txt","r",stdin);
    40     int t;
    41     scanf("%d",&t);
    42     while(t--){
    43         int m,n,ans=1;len=0;
    44         scanf("%d%d",&n,&m);
    45         for(int i=1;i<=n;i++)
    46             scanf("%d",&a[i]);
    47         for(int i=1;i<=n;i++)
    48             scanf("%d",&b[i]),val[i]=b[i]-a[i];
    49         for(int i=1;i<=n;i++)
    50             f[i]=i,belong[i]=-1,Head[i]=0;
    51         for(int i=1;i<=m;i++){
    52             scanf("%d%d%d",&p[i].t,&p[i].u,&p[i].v);
    53             if(p[i].t==2){
    54                 Mer(p[i].u,p[i].v);//合并操作二
    55             }
    56         }
    57         for(int i=1;i<=m;i++){
    58             if(p[i].t==1){
    59                 Ins(find(p[i].u),find(p[i].v));//这里已经缩点所以要合并根
    60                 Ins(find(p[i].v),find(p[i].u));
    61             }
    62         }
    63         for(int i=1;i<=n;i++){
    64             if(find(i)==i&&belong[i]==-1){
    65                 flag=sum=0;
    66                 dfs(i,0);
    67                 for(int x=Head[i];x;x=e[x].next){
    68                     if(e[x].to==i)flag=1;//自环
    69                 }
    70                 if(Head[i]==0&&sum!=0)ans=0;//没有边连入
    71                 else if(flag==1&&sum%2!=0)ans=0;//奇数环
    72                 else if(flag==0&&sum!=0)ans=0;//偶数环
    73             }
    74         }
    75         if(ans)printf("YES
    ");
    76         else printf("NO
    ");
    77     }
    78 }
  • 相关阅读:
    win7(64bit)python相关环境模块搭建
    memcached在windows下的安装与命令使用方法
    pomelo流程
    pomelo 初始化配置...
    pomelo组件..
    <转>如何高效快速看懂Android源码
    源码学习
    计划
    Android面试题集锦 (转)
    Android 面试题(转)
  • 原文地址:https://www.cnblogs.com/anyixing-fly/p/12438806.html
Copyright © 2011-2022 走看看