NOIPの模拟_2016_7_20_t2_Graph Coloring

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值