NOIPの模拟_2016_7_20_t2_Graph Coloring

来源:互联网 发布:松下网络摄像机出厂ip 编辑:程序博客网 时间:2024/06/09 23:17

Description

现在你有一张无向图包含n个节点m条边。最初,每一条边都是蓝色或者红色。每一次你可以将一个节点连接的所有边变色(从红变蓝,蓝变红)。
找到一种步数最小的方案,使得所有边的颜色相同。

Input

第一行包含两个数n,m(1<=n,m<=100000)分别代表节点数和边的数量
接下来m行描述边,第i行ui,vi,ci,代表ui有一条颜色为ci的边与vi相连(ci是B或者是R),B代表蓝色,R代表红色。数据保证没有自环的边。

Output

如果没有方案就输出-1。否则第一行输出k代表最小的步数

Sample Input

输入1:
3 3
1 2 B
3 1 R
3 2 B

输入2:
3 3
1 2 B
3 1 R
3 2 B

输入3:
4 5
1 2 R
1 3 R
2 3 B
3 4 B
1 4 B

Sample Output

输出1:
1

输出2:
2

输出3:
-1

Data Constraint

对于30%数据,n<=20,m<=20

题目の大意:

给你一堆点,还有一堆边,每条边上有一个“R”或者“B”每一次可以把与一个点相邻的边全部换一种颜色(红变蓝蓝变红~)求最少的步数

比赛时の想法:

首先观摩一下数据の规模,105级别,于是就开始想nlogn的做法想着想着发现每一个点最多只会按一次,这是十分显然的,因为按两次对答案的贡献就为零了,于是在这个基础上继续想,然后我就发现如果边的目标颜色以及当前颜色确定,而且有一边的颜色确定,那么另外一边的颜色也是确定的。当时就想着可以分颜色选什么和第一个点取不取4种情况讨论,但是这个想法很好显然是错误的 233333333333

解法:

在前面想法的基础上,我们可以发现那个图不一定是一个联通图,ta可能是由多个块组成的,那么我们可以先做一次bfs分块,然后分全部染成红色和全部染成蓝色两种情况讨论,由与每个块都是相对独立的,于是我们可以对每个块分开讨论,对于每个块我们也是分成第一个点取或不取讨论,然后把对于每一个块取或不取的较小的答案加起来,然后把染成红色和染成蓝色需要的步数比较一下,输出较小的那个就可以了。注意如果在做某一个块时出现了不合法的情况,那么后面的块都不用做了,对于这个目标颜色所需“步数”为-1。

吐槽

哈哈哈哈又到了吐槽的时间啦,因为我太垃圾了,所以打的代码也很捞,别人2000byte的代码量被我强行打到6500byte,结果超级难调,看来要早日皈依C++了红红火火恍恍惚惚。

代码

稍微看一下就可以理解的超好超级垃圾的代码233

var    a,b:array[0..200005,1..2]of longint;    color:array[0..200005]of char;    bb,bz:array[0..100005]of boolean;    cc,skt,h:array[0..100005]of longint;    i,j,k,l,m,n,ans,tot,kk,ans1,ans2:longint;procedure qsort(l,r:longint);var    i,j,mid:longint;begin    i:=l;    j:=r;    mid:=a[(i+j) div 2,1];    repeat        while a[i,1]<mid do inc(i);        while a[j,1]>mid do dec(j);        if i<=j then        begin            a[0]:=a[i];            a[i]:=a[j];            a[j]:=a[0];            color[0]:=color[i];            color[i]:=color[j];            color[j]:=color[0];            inc(i);            dec(j);        end;    until i>j;    if i<r then qsort(i,r);    if l<j then qsort(l,j);end;procedure getred(zz:longint;ppp:boolean);var    i,j,k,x,y:longint;    xx:boolean;begin    skt[0]:=0;    tot:=0;    if ppp=true then    begin        tot:=1;        inc(skt[0]);        skt[skt[0]]:=zz;    end;    i:=1;    h[1]:=zz;    bz[zz]:=true;    j:=0;    xx:=false;    while j<i do    begin        if xx=true then break;        inc(j);        x:=h[j];        for k:=b[x,1] to b[x,2] do        if k>0 then        begin            y:=a[k,2];            if bz[y]=true then            begin                if (color[k]='R') and (bb[x]<>bb[y]) then                begin                    xx:=true;                    tot:=-1;                    break;                end else                if (color[k]='B') and (bb[x]=bb[y]) then                begin                    xx:=true;                    tot:=-1;                    break;                end;            end else            begin                bz[y]:=true;                if color[k]='R' then                begin                    if bb[x]=false then bb[y]:=false else                    begin                        bb[y]:=true;                        inc(tot);                        inc(skt[0]);                        skt[skt[0]]:=y;                    end;                end else                begin                    if bb[x]=false then                    begin                        bb[y]:=true;                        inc(tot);                        inc(skt[0]);                        skt[skt[0]]:=y;                    end else bb[y]:=false;                end;                inc(i);                h[i]:=y;            end;        end;    end;    if (tot<ans) and (tot<>-1) then ans:=tot;    for j:=1 to i do bz[h[j]]:=false;    for j:=1 to skt[0] do bb[skt[j]]:=false;end;procedure init;begin    readln(n,m);    for i:=1 to m do    begin        readln(a[i,1],a[i,2],color[i],color[i]);        a[m+i,1]:=a[i,2];        a[m+i,2]:=a[i,1];        color[m+i]:=color[i];    end;    m:=m*2;    qsort(1,m);    b[a[1,1],1]:=1;    for i:=2 to m do    if a[i,1]<>a[i-1,1] then    begin        b[a[i-1,1],2]:=i-1;        b[a[i,1],1]:=i;    end;    b[a[m,1],2]:=m;end;procedure getblue(zz:longint;ppp:boolean);var    i,j,k,x,y:longint;    xx:boolean;begin    skt[0]:=0;    tot:=0;    if ppp=true then    begin        tot:=1;        inc(skt[0]);        skt[skt[0]]:=zz;    end;    i:=1;    h[1]:=zz;    bz[zz]:=true;    j:=0;    xx:=false;    while j<i do    begin        if xx=true then break;        inc(j);        x:=h[j];        for k:=b[x,1] to b[x,2] do        if k>0 then        begin            y:=a[k,2];            if bz[y]=true then            begin                if (color[k]='B') and (bb[x]<>bb[y]) then                begin                    xx:=true;                    tot:=-1;                    break;                end else                if (color[k]='R') and (bb[x]=bb[y]) then                begin                    xx:=true;                    tot:=-1;                    break;                end;            end else            begin                bz[y]:=true;                if color[k]='B' then                begin                    if bb[x]=false then bb[y]:=false else                    begin                        bb[y]:=true;                        inc(tot);                        inc(skt[0]);                        skt[skt[0]]:=y;                    end;                end else                begin                    if bb[x]=false then                    begin                        bb[y]:=true;                        inc(tot);                        inc(skt[0]);                        skt[skt[0]]:=y;                    end else bb[y]:=false;                end;                inc(i);                h[i]:=y;            end;        end;    end;    if (tot<ans) and (tot<>-1) then ans:=tot;    for j:=1 to i do bz[h[j]]:=false;    for j:=1 to skt[0] do bb[skt[j]]:=false;end;procedure bfs(x:longint);var    i,j:longint;    q:array[0..100005]of longint;begin    i:=1;    j:=0;    fillchar(q,sizeof(q),0);    q[1]:=x;    inc(k);  //  cc[x]:=k;    while j<i do    begin        inc(j);        for l:=b[q[j],1] to b[q[j],2] do        if bb[a[l,2]]=false then        begin          //  cc[a[l,2]]:=k;            inc(i);            q[i]:=a[l,2];            bb[a[l,2]]:=true;        end;    end;end;procedure de;begin    k:=0;    for i:=1 to n do    if bb[i]=false then    begin        bfs(i);        cc[k]:=i;    end;    fillchar(bb,sizeof(bb),false);end;begin  //  assign(input,'2.in'); reset(input);    init;    de;    kk:=k;    for i:=1 to kk do    begin       // fillchar(bb,sizeof(bb),false);        bb[cc[i]]:=true;        ans:=maxlongint;        getred(cc[i],true);       // fillchar(bb,sizeof(bb),false);        getred(cc[i],false);        if ans=maxlongint then ans:=-1;        if ans=-1 then        begin            ans1:=-1;            break;        end;        ans1:=ans1+ans;    end;    for i:=1 to kk do    begin      //  fillchar(bb,sizeof(bb),false);        bb[cc[i]]:=true;        ans:=maxlongint;        getblue(cc[i],true);       // fillchar(bb,sizeof(bb),false);        getblue(cc[i],false);        if ans=maxlongint then ans:=-1;        if ans=-1 then        begin            ans2:=-1;            break;        end;        ans2:=ans2+ans;    end;    if ans1=-1 then    begin        if ans2=-1 then writeln(-1) else writeln(ans2);    end else    begin        if ans2=-1 then writeln(ans1) else        begin            if ans2>ans1 then writeln(ans1) else writeln(ans2);        end;    end;  //  close(input);end.
1 0
原创粉丝点击