• [ZJOI2012]网络


    题目描述

    有一个无向图G,每个点有个权值,每条边有一个颜色。这个无向图满足以下两个条件:

    1. 对于任意节点连出去的边中,相同颜色的边不超过两条。

    2. 图中不存在同色的环,同色的环指相同颜色的边构成的环。

    在这个图上,你要支持以下三种操作:

    1. 修改一个节点的权值。

    2. 修改一条边的颜色。

    3. 查询由颜色c的边构成的图中,所有可能在节点u到节点v之间的简单路径上的节点的权值的最大值。

    输入输出格式

    输入格式:

    输入文件network.in的第一行包含四个正整数N, M, C, K,其中N为节点个数,M为边数,C为边的颜色数,K为操作数。

    接下来N行,每行一个正整数vi,为节点i的权值。

    之后M行,每行三个正整数u, v, w,为一条连接节点u和节点v的边,颜色为w。满足1 ≤ u, v ≤ N,0 ≤ w < C,保证u ≠ v,且任意两个节点之间最多存在一条边(无论颜色)。

    最后K行,每行表示一个操作。每行的第一个整数k表示操作类型。

    1. k = 0为修改节点权值操作,之后两个正整数x和y,表示将节点x的权值vx修改为y。

    2. k = 1为修改边的颜色操作,之后三个正整数u, v和w,表示将连接节点u和节点v的边的颜色修改为颜色w。满足0 ≤ w < C。

    3. k = 2为查询操作,之后三个正整数c, u和v,表示查询所有可能在节点u到节点v之间的由颜色c构成的简单路径上的节点的权值的最大值。如果不存在u和v之间不存在由颜色c构成的路径,那么输出“-1”。
    输出格式:

    输出文件network.out包含若干行,每行输出一个对应的信息。

    1. 对于修改节点权值操作,不需要输出信息。

    2. 对于修改边的颜色操作,按以下几类输出:

    a) 若不存在连接节点u和节点v的边,输出“No such edge.”。

    b) 若修改后不满足条件1,不修改边的颜色,并输出“Error 1.”。

    c) 若修改后不满足条件2,不修改边的颜色,并输出“Error 2.”。

    d) 其他情况,成功修改边的颜色,并输出“Success.”。

    输出满足条件的第一条信息即可,即若同时满足b和c,则只需要输出“Error 1.”。

    1. 对于查询操作,直接输出一个整数。

    输入输出样例

    输入样例#1:
    4 5 2 7
    1
    2
    3
    4
    1 2 0
    1 3 1
    2 3 0
    2 4 1
    3 4 0
    2 0 1 4
    1 1 2 1
    1 4 3 1
    2 0 1 4
    1 2 3 1
    0 2 5
    2 1 1 4
    输出样例#1:
    4
    Success.
    Error 2.
    -1
    Error 1.
    5

    说明

    颜色0为实线的边,颜色1为虚线的边,

    由颜色0构成的从节点1到节点4的路径有1 – 2 – 4,故max{v1, v2, v4} = max{ 1, 2, 4 } = 4。

    将连接节点1和节点2的边修改为颜色1,修改成功,输出“Success.”

    将连接节点4和节点3的边修改为颜色1,由于修改后会使得存在由颜色1构成的环( 1 – 2 – 4 – 3 – 1 ),不满足条件2,故不修改,并输出“Error 2”。

    不存在颜色0构成的从节点1到节点4的边,输出“-1”。

    将连接节点2和节点3的边修改为颜色1,由于修改后节点2的连出去的颜色为1的边有3条,故不满足条件1,故不修改,并输出“Error 1.”。

    将节点2的权值修改为5。

    由颜色1构成的从节点1到节点4的路径有 1 – 2 – 4,故max{v1, v2, v4} = max{ 1, 5, 4 } = 5。

    【数据规模】

    对于30%的数据:N ≤ 1000,M ≤ 10000,C ≤ 10,K ≤ 1000。

    另有20%的数据:N ≤ 10000,M ≤ 100000,C = 1,K ≤ 100000。

    对于100%的数据:N ≤ 10000,M ≤ 100000,C ≤ 10,K ≤ 100000。

     
     
    考虑C<=10,那么就维护CLCT.
    对于0操作,直接把每个LCT里面的权值修改.
    对于1操作,可以先用map记录下每条边的颜色(其实最好是不用map,只是比较方便,卡着时间过了就没管了).然后就先进行一大堆判断,然后把原来那条边删掉,新加一条边.对于Error1的处理,每个点维护一个cnt,表示这个点的度数,因为在旋转的操作中这个值不会变,那么就link的时候+1,cut的时候-1.
    对于2操作,每个点维护一个zd表示以这个点为根的splay子树(不是原树)里面的最大值,查询的时候先把x变成root,然后access
    y,splay y.答案就是zd[y].
    cutRotate时都要更新这个zd.
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstdlib>
      4 #include<cstring>
      5 #include<string>
      6 #include<algorithm>
      7 #include<map>
      8 #include<complex>
      9 #include<queue>
     10 #include<stack>
     11 #include<cmath>
     12 #include<set>
     13 #include<vector>
     14 #define maxn 20010
     15 #define pre t[x].fa
     16 #define ls t[x].ch[0]
     17 #define rs t[x].ch[1]
     18 #define RG register
     19 using namespace std;
     20 struct LCT{
     21   struct data{int w,ch[2],fa,lazy,cnt,zd;}t[maxn];
     22   inline bool son(RG int x){return t[pre].ch[1]==x;}
     23   inline bool isrt(RG int x){return t[pre].ch[0]!=x && t[pre].ch[1]!=x;}
     24   inline void updata(int x){t[x].zd=max(t[x].w,max(t[ls].zd,t[rs].zd));}
     25   inline void down(RG int x){
     26     if(t[x].lazy==1)
     27       swap(ls,rs),t[ls].lazy^=1,t[rs].lazy^=1,t[x].lazy=0;
     28   }
     29   void pd(int x){if(!isrt(x)) pd(pre);down(x);}
     30   inline void Rotate(RG int x){
     31     int f=t[x].fa,g=t[f].fa,c=son(x);
     32     if(!isrt(f)) t[g].ch[son(f)]=x;
     33     t[x].fa=g;
     34     t[f].ch[c]=t[x].ch[c^1],t[t[f].ch[c]].fa=f;
     35     t[x].ch[c^1]=f,t[f].fa=x;
     36     updata(f),updata(x);
     37   }
     38   inline void Splay(RG int x){
     39     pd(x);
     40     for(;!isrt(x);Rotate(x)){
     41       if(!isrt(pre)) Rotate(son(pre)==son(x)?pre:x);
     42     }
     43   }
     44   inline void access(RG int x){
     45     for(RG int y=0;x;y=x,x=pre) Splay(x),rs=y,updata(x);
     46   }
     47   inline void makert(RG int x){
     48     access(x),Splay(x),t[x].lazy^=1;
     49   }
     50   inline int findrt(RG int x){
     51     access(x),Splay(x);
     52     while(ls) down(x),x=ls;
     53     return x;
     54   }
     55   inline void link(RG int x,RG int y){
     56     makert(x),t[x].fa=y;t[x].cnt++,t[y].cnt++;
     57   }
     58   inline void cut(RG int x,RG int y){
     59     makert(x),access(y),Splay(y);
     60     t[y].ch[0]=t[x].fa=0;
     61     t[x].cnt--,t[y].cnt--;
     62     updata(y);
     63   }
     64   inline void query(int x,int y){
     65     if(findrt(x)!=findrt(y)) printf("-1
    ");
     66     else{
     67       makert(x),access(y),Splay(y);
     68       printf("%d
    ",t[y].zd);
     69     }
     70   }
     71 }lct[12];
     72 struct edge{
     73   int x,y;
     74   bool operator < (const edge &h) const{
     75     if(h.x!=x)return h.x<x;else return h.y<y;
     76   }
     77 };
     78 map<edge,int>mp;
     79 int main(){
     80   int n,m,C,qes,x,y,z,type;
     81   scanf("%d%d%d%d",&n,&m,&C,&qes);
     82   for(RG int i=1;i<=n;i++){
     83     scanf("%d",&x);
     84     for(RG int j=0;j<C;j++)lct[j].t[i].w=x;
     85   }
     86   for(RG int i=1;i<=m;i++){
     87     scanf("%d%d%d",&x,&y,&z),lct[z].link(x,y);
     88     edge e1=(edge){x,y},e2=(edge){y,x};
     89     mp[e1]=mp[e2]=z;
     90   }
     91   for(RG int i=1;i<=qes;i++){
     92     scanf("%d",&type);
     93     if(type==0){
     94       scanf("%d%d",&x,&y);
     95       for(int j=0;j<C;j++) lct[j].t[x].w=y,lct[j].Splay(x);
     96     }
     97     if(type==1){
     98       scanf("%d%d%d",&x,&y,&z);
     99       edge e1=(edge){x,y},e2=(edge){y,x};
    100       if(!mp.count((e1))){printf("No such edge.
    ");continue;}
    101       int las=mp[e1];
    102       if(las==z){printf("Success.
    ");continue;}
    103       if(lct[z].t[x].cnt>=2 || lct[z].t[y].cnt>=2){printf("Error 1.
    ");continue;}
    104       if(lct[z].findrt(x)==lct[z].findrt(y)){printf("Error 2.
    ");continue;}
    105       lct[las].cut(x,y);
    106       mp[e1]=mp[e2]=z;
    107       lct[z].link(x,y);
    108       printf("Success.
    ");
    109     }
    110     if(type==2) scanf("%d%d%d",&z,&x,&y),lct[z].query(x,y);
    111   }
    112   return 0;
    113 }
  • 相关阅读:
    [每日一题]石子合并 -- 区间DP
    [每日一题]: 最长上升子序列 AND 最长不上升子序列
    [每日一题]:最大子矩阵和
    入门DP--最大子段和
    [转载]:正确的提问方式
    springmvc.xml
    service层springservice.xml文件
    aop切面配置
    配置事务通知
    短信验证
  • 原文地址:https://www.cnblogs.com/pantakill/p/7282459.html
Copyright © 2020-2023  润新知